Простой аналог Once можно сделать через канал как взаимное исключение и флаг выполнения. Все обращения к флагу должны происходить под одной блокировкой.
Как написать WaitGroup или Once без библиотеки sync?
Простой аналог Once можно сделать через канал как взаимное исключение и флаг выполнения. Все обращения к флагу должны происходить под одной блокировкой.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Простой аналог Once можно сделать через канал как взаимное исключение и флаг выполнения. Все обращения к флагу должны происходить под одной блокировкой.
type Once struct {
gate chan struct{}
done bool
}
func NewOnce() *Once {
return &Once{gate: make(chan struct{}, 1)}
}
func (o *Once) Do(f func()) {
o.gate <- struct{}{}
defer func() { <-o.gate }()
if o.done { return }
o.done = true
f()
}
Конкурентные вызовы ждут завершения первого; после panic повторного выполнения не будет. Нужен конструктор, нулевое значение не готово к работе, объект нельзя копировать. Рекурсивный вызов Do на том же объекте заблокируется. В прикладном коде лучше стандартный sync.Once: этот вариант демонстрирует принцип, а не улучшает библиотеку.