Пакет sync
Каналы — не единственный инструмент. Для простых задач синхронизации
стандартная библиотека предлагает пакет sync.
sync.WaitGroup
Ожидание завершения группы горутин:
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(n int) {
defer wg.Done()
fmt.Println("готово:", n)
}(i)
}
wg.Wait()
В Go 1.25+ можно короче: wg.Go(func() { ... }).
sync.Mutex
Защита разделяемых данных от гонок:
type Counter struct {
mu sync.Mutex
n int
}
func (c *Counter) Inc() {
c.mu.Lock()
defer c.mu.Unlock()
c.n++
}
sync.RWMutex позволяет множеству читателей работать одновременно
(RLock/RUnlock), а писателю — эксклюзивно.
sync.Once
Гарантирует однократное выполнение, например ленивую инициализацию:
var (
once sync.Once
cfg *Config
)
func GetConfig() *Config {
once.Do(func() {
cfg = loadConfig()
})
return cfg
}
sync/atomic
Для простых счётчиков удобны атомарные типы:
var hits atomic.Int64
hits.Add(1)
fmt.Println(hits.Load())
Каналы или мьютексы?
- Каналы — передача владения данными, конвейеры, сигналы о событиях.
- Мьютексы — защита состояния внутри структуры (кэш, счётчик).