Для понимания работы примера из поста о синглтон паттерне рассмотрим тип sync.Once и его метод Do.
Once это объект, который выполнит только однократное действие. В приведенном ниже примере запускается 10 go-процедур, вызывающих функцию, печатающую строку "Only once", но за счет использования sync.Once, несмотря на 10 вызовов, функция выполнится лишь однократно.
package main
import (
"fmt"
"sync"
)
func main() {
var once sync.Once
onceBody := func() {
fmt.Println("Only once")
}
done := make(chan bool)
for i := 0; i < 10; i++ {
go func() {
once.Do(onceBody)
done <- true
}()
}
for i := 0; i < 10; i++ {
<-done
}
}
Вывод
Only once
Запустить в песочнице play.golang.org
Метод Do для типа Once
func (o *Once) Do(f func())
Метод Do вызывает функцию f только если Do был вызван впервые для этого инстанса Once. Другими словами для данной переменной
var once Once
если once.Do(f) вызывается несколько раз, только первый вызов выполнит f, даже если f имеет различное значение в каждом вызове. Если требуется выполнять f для каждого вызова, тогда необходим новый экземпляр Once на каждый вызов.
Do предназначен для инициализации, которая должна быть запущена ровно один раз. Поскольку f является неликадным, может потребоваться использование литерала функции для захвата аргументов функции, которая вызывается Do:
config.once.Do(func() { config.init(filename) })
Поскольку никакой вызов Do не возвращается до тех пор, пока не вернется один вызов f, если f вызовет Do, это приведет к взаимоблокировке.
Если f вызывает panic, Do считает, что f выполнила возврат (return); последующие вызовы Do будут возвращаться без вызова f.
Читайте также:
Комментариев нет:
Отправить комментарий