import (
"strings"
)
func normalize(s string) string {
var sb strings.Builder
for _, r := range s {
switch {
case '0' <= r && r <= '9':
case r == '+':
default:
continue
}
sb.WriteRune(r)
}
return sb.String()
}
import (
"regexp"
"strings"
)
var re = regexp.MustCompile(`(?i)[\d\+]+`)
func normalize(s string) string {
var sb strings.Builder
subs := re.FindAllStringSubmatch(s, -1)
for _, sub := range subs {
sb.WriteString(sub[0])
}
return sb.String()
}
var re = regexp.MustCompile(`(?m)[^+\d]`)
var str = `+999 (99)-999 9999`
fmt.Println(re.ReplaceAllString(str, ""))
package main
import "api"
func main(){
...
r := api.NewRouter(...)
http.ListenAndServe(...)
}
package api
import (
"app"
"models"
)
func NewRouter(...) ...{
// Инициализация роутера, регистрация обработчиков и т.д.
...
return r
}
func handleEndpointA(w http.ResponseWriter, r *http.Request){
// Извлечение, валидация параметров.
// Извлечение соединений БД и друхих хранилищ из контекста.
// Обработка ошибок.
...
result, err := app.DoTaskA(ctx, db, paramA, paramB)
...
render(w, result)
}
func handleEndpointB(w http.ResponseWriter, r *http.Request){
...
result, err := app.DoTaskB(ctx, db, paramC)
...
render(w, result)
}
package app
import(
"database"
"models"
)
func DoTaskA(ctx, db, paramA, paramB) (result, err){
// Какие-то манипуляции с параметрами.
...
// Запрос в бд.
modelA, err := database.RequestA(ctx, db, param)
...
return result, err
}
package database
import (
"models"
)
func RequestA(ctx, db, param) (result, err) {
// Не забываем поставить таймаут на запрос к БД.
ctx, cancel = context.WithTimeout(ctx, defaultRequestTimeout)
defer cancel()
...
result, err := db.DoRequest(ctx, ...)
...
return result, err
}
func handle(w http.ResponseWriter, r *http.Request){
fileToZip, _ := os.Open("filepath")
defer fileToZip.Close()
// NewWriter returns a new Writer writing a zip file to w.
zipWriter := zip.NewWriter(w)
defer zipWriter.Close()
info, _ := fileToZip.Stat()
header, _ := zip.FileInfoHeader(info)
// Change to deflate to gain better compression
// see http://golang.org/pkg/archive/zip/#pkg-constants
header.Method = zip.Deflate
// CreateHeader adds a file to the zip archive using the provided FileHeader
// for the file metadata.
// This returns a Writer to which the file contents should be written.
writer, _ := zipWriter.CreateHeader(header)
io.Copy(writer, fileToZip)
}
Golang/Gin codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the RealWorld spec and API.
package main
import (
"fmt"
"regexp"
)
func main() {
re := regexp.MustCompile(`(gopher){2}`)
fmt.Println(re.MatchString("gopher"))
fmt.Println(re.MatchString("gophergopher"))
fmt.Println(re.MatchString("gophergophergopher"))
}
const n = 4 // длина идентификатора комнаты в байтах
type (
noop struct{}
WebSocket struct{} // сокет
Sockets []WebSocket
RoomKey [n]byte
Index uint32
Room map[Index] struct{}
Rooms map[RoomKey] Room
)
var sockets = make(Sockets, 0, 2000000)
var rooms = make(Rooms, 1000)
var lastSocketRoomKey RoomKey
func insert(ws WebSocket, rk RoomKey){
room, _ := rooms[rk]
// тут создание комнаты, если ее нет
// ...
sockets = append(sockets, ws)
last := len(sockets) - 1
room[Index(last)] = noop{}
// сохраним ключ комнаты последнего сокета
// чтобы можно было исправить индекс при удалении
copy(lastSocketRoomKey[:], rk[:])
}
func remove(i Index, rk RoomKey){
// удаляем сокет,
// переместив последний в массиве на место удаляемого
last := len(sockets) - 1
sockets[i] = sockets[last]
sockets = sockets[:last]
// удаляем сокет из комнаты
room, _ := rooms[rk]
delete(room, Index(i))
// чиним индекс перемещенного сокета
roomOfLast := rooms[lastSocketRoomKey]
delete(roomOfLast, Index(last))
roomOfLast[Index(i)] = noop{}
}
for _, index := range rooms[roomkey]{
// sockets[index] -- сокет в комнате с roomkey
// т.к. из-за особенности структуры искать сокет в комнате получается невыгодно долго,
// придется удалять закрытые сокеты "ленивым" способом во время рассылки,
// либо заполнять массив индексов и после уже удалять эти сокеты из общего хранилища
// функцией remove(index, roomkey)
}