Существует два разных подхода к очистке горутина.
Используйте канал уничтожения, чтобы сообщить об отмене, и канал готово, чтобы указать, что выполнение программы было прекращено.
type Worker struct {
Done chan struct{}
Kill chan struct{}
Jobs chan Job
}
func (w *Worker) Run() {
defer func() {
w.Done <- struct{}{}
}
for {
select {
case <-w.Kill:
return
case j := <-w.Jobs:
// Do some work
}
}
go w.Run()
w.Kill <- struct{}{}
Используйте context
для отмены
type Worker struct {
Ctx context.Context
Cancel context.CancelFunc
Jobs chan Job
}
func (w *Worker) Run() {
for {
select {
case <-w.Ctx.Done():
return
case j := <-w.Jobs:
// Do some work
}
}
go w.Run()
w.Cancel()
Каковы плюсы / минусы каждого подхода? Какой из них я должен по умолчанию?
Я понимаю, что если я хочу убить дерево взаимосвязанных подпрограмм, я должен использовать контекстный подход, но давайте просто скажем, что у меня есть простой рабочий, который не запускает другие подпрограммы внутренне.