Как написать WaitGroup или Once без библиотеки sync?

Простой аналог Once можно сделать через канал как взаимное исключение и флаг выполнения. Все обращения к флагу должны происходить под одной блокировкой.

Короткий ответ

Что ответить на собеседовании

Простой аналог 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: этот вариант демонстрирует принцип, а не улучшает библиотеку.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее