Один раз: sync.Once
Условие задачи
Реализуй инициализацию ресурса, которая выполняется только один раз, даже если из разных горутин приходит много запросов. Пример: подключение к базе данных или загрузка конфигурации.
package main
import (
"fmt"
"sync"
)
var once sync.Once
func initResource() {
fmt.Println("Ресурс инициализирован")
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// TODO: initResource должен вызваться только один раз
}()
}
wg.Wait()
}
package main
import (
"fmt"
"sync"
)
var once sync.Once
func initResource() {
fmt.Println("Ресурс инициализирован")
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
// TODO: initResource должен вызваться только один раз
}()
}
wg.Wait()
}
Подсказка
- Используй once.Do(...) - Метод Do гарантирует, что переданная функция будет вызвана только один раз независимо от количества вызовов.
Решение
sync.Once — безопасный способ гарантировать однократное выполнение. Удобен для lazy-инициализации.
package main
import (
"fmt"
"sync"
)
var once sync.Once
func initResource() {
fmt.Println("Ресурс инициализирован")
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
once.Do(initResource)
}()
}
wg.Wait()
}
package main
import (
"fmt"
"sync"
)
var once sync.Once
func initResource() {
fmt.Println("Ресурс инициализирован")
}
func main() {
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func() {
defer wg.Done()
once.Do(initResource)
}()
}
wg.Wait()
}