• Избегание дублирования состояния в памяти
• Работа в многопоточной среде и потокобезопасный доступ к общей структуре
• Затрудняет тестирование (невозможно подменить зависимости)
• Провоцирует на глобальные сингл-точки сбоя (если объект упал — всё развалилось)
• Препятствует масштабируемости при переходе к микросервисной архитектуре
privatesyncPlease open Telegram to view this post
VIEW IN TELEGRAM
👍3🌚2👏1
context.Background() или context.TODO()Когда вы работаете с Go-контекстами, легко запутаться: оба выглядят одинаково, оба ничего не делают — но используются по-разному.
context.Background() main()context.TODO() Такой контекст часто используется в
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱3❤2
sync.MutexРабочий
package main
import (
"fmt"
"sync"
)
type singleton struct {
data string
}
var (
instance *singleton
mu sync.Mutex
)
func GetInstance() *singleton {
if instance == nil {
mu.Lock()
defer mu.Unlock()
if instance == nil {
instance = &singleton{data: "initialized"}
}
}
return instance
}
func main() {
s := GetInstance()
fmt.Println("Singleton data:", s.data)
}
if instance == nil mu.Lock() sync.OncePlease open Telegram to view this post
VIEW IN TELEGRAM
❤4👏1
context в Go вы знаетеctx := context.Background()
ctx, cancel := context.WithTimeout(ctx, 3*time.Second)
defer cancel()
• WithCancel
• WithTimeout
• WithDeadline
• WithValue
Каждая из этих функций создаёт дочерний контекст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🥱1
sync.Once, если уже есть мьютексыЕсли вы хотите
sync.Oncepackage main
import (
"fmt"
"sync"
)
type singleton struct {
config string
}
var (
once sync.Once
instance *singleton
)
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{config: "default"}
})
return instance
}
func main() {
s := GetInstance()
fmt.Println("Singleton config:", s.config)
}
sync.OnceGetInstance вызывается из Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍2💯1
ctx.Done() внутри горутин и что произойдёт, если этого не делатьКонтекст используется
ctx.Done() go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("goroutine stopped:", ctx.Err())
return
case <-time.After(1 * time.Second):
fmt.Println("working...")
}
}
}(ctx)Если не слушать
ctx.Done(), вы получите:• Зависание приложения
• Недетерминированное поведение при отмене
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍2
Оцените их по шкале 🔥,❤️,👍,😢, 🥱,
где 🔥 — это супер, а 🥱 — это скучно.
Также приветствуется фидбек в комментариях.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍24🔥13❤7🥱1
init() не считается ленивойinit().init()package main
import (
"fmt"
)
type singleton struct {
config string
}
var instance *singleton
func init() {
instance = &singleton{config: "preloaded"}
}
func GetInstance() *singleton {
return instance
}
func main() {
s := GetInstance()
fmt.Println("Singleton config:", s.config)
}
• Инициализация происходит
main()• Синхронизация не требуется
init()• Порядок инициализации между пакетами
•
•
•
• Нарушает
• Затрудняет
• Может
Please open Telegram to view this post
VIEW IN TELEGRAM
😁4❤2👍1
context в юнит-тестахcontext — мощный инструмент,Чтобы избежать зависаний и утечек в юнит-тестах, всегда создавайте
context ctx, cancel := context.WithTimeout(context.Background(), 500*time.Millisecond)
defer cancel()
• Это гарантирует:
Ресурсы будут высвобождены
Горутины получат сигнал на завершение
Если ваш тест зависает
ctx.Done()Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
sync.Mutex, sync.Once или init()Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👍4
select, если можно просто читать из каналаВ Go оператор
select switchС его помощью можно:
• Управлять конкурентными потоками без блокировок
• Не блокироваться, если добавить
defaultselect {
case msg := <-ch1:
fmt.Println("Received from ch1:", msg)
case ch2 <- 42:
fmt.Println("Sent 42 to ch2")
default:
fmt.Println("Nothing ready")
}Если
ch1 или ch2 готовы Если ни один канал не активен
defaultselectPlease open Telegram to view this post
VIEW IN TELEGRAM
👍5❤2🤔1
Singleton может мешать тестированию
type Storage interface {
Get(key string) string
}func ProcessData(s Storage) { ... }// В тестовых сборках
func resetSingleton() {
instance = nil
once = sync.Once{}
}
❕Warning
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🤔1
select выбирает случайноОдно из важных свойств
select в Go select {
case msg := <-ch1:
fmt.Println("ch1:", msg)
case msg := <-ch2:
fmt.Println("ch2:", msg)
}Если и
ch1, и ch2 доступны Это исключает жёсткий приоритет каналов
Это нужно для предотвращения "голодания"
Please open Telegram to view this post
VIEW IN TELEGRAM
😁10👍3🌚2
Отношение happens-before гарантирует
Please open Telegram to view this post
VIEW IN TELEGRAM
😁3👏1🎉1
Оцените их по шкале 🔥,❤️,👍,😢, 🥱,
где 🔥 — это супер, а 🥱 — это скучно.
Также приветствуется фидбек в комментариях.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍27🔥12😢7❤5👾1
Redis поддерживает два механизма сохранения данных:
Эти два метода
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥4
sync/atomicАтомарная операция
Store Load той же переменной Инициализация
main(), что Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Паттерн «Функциональные опции»
Этот подход идеален,
Пример
type Server struct {
host string
port int
protocol string
}
func NewServer(host string, port int) *Server {
return &Server{host: host, port: port, protocol: "http"}
}Реализация функциональных опций
type ServerOption func(*Server)
func WithPort(port int) ServerOption {
return func(s *Server) {
s.port = port
}
}NewServer:func NewServer(host string, opts ...ServerOption) *Server {
server := &Server{host: host, port: 443, protocol: "https"}
for _, opt := range opts {
opt(server)
}
return server
}Теперь можно
server1 := NewServer("localhost") // с портом по умолчанию
server2 := NewServer("localhost", WithPort(8080)) // с портом 8080Этот подход позволяет добавлять параметры
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15🤔7👏1🌚1
Планировщик Go отвечает за
• G (goroutine)
• M (machine thread)
• P (processor)
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11🤔2
Дженерики в Go — это механизм, введенный в версии 1.18
Дженерики позволяют
• Уменьшение
• Повышенная
• Увеличение
До введения дженериков, разработчики использовали интерфейсы и преобразование типов для обеспечения гибкости.
func MinInts(arr []int) int { /*...*/ }
func MinFloats(arr []float64) float64 { /*...*/ }Теперь с использованием дженериков можно создать
func Min[T comparable](arr []T) T { /*...*/ }Здесь
T — это comparable указывает,Без дженериков:
type Queue struct {
data []interface{}
}Использование
interface{} требует С дженериками:
type Queue[T any] struct {
data []T
}Здесь
T может быть Внедрение дженериков в Go получило положительный отклик
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18
Escape analysis — это техника
В Go
Компилятор
Если же переменная «выходит» — например,
func sum(a, b int) int {
result := a + b
return result
}В данном случае переменная
result func newInt() *int {
result := 42
return &result
}Здесь переменная
result выходит за пределы var globalVar *int
func setGlobalVar() {
x := 100
globalVar = &x
}
Переменная
x Escape analysis помогает управлять
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👏3🤔1