В Go нельзя принудительно убить горутину. Она должна сама проверять сигнал остановки.
Способ 1: context (рекомендуется)
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("stopped")
return
default:
doWork()
}
}
}(ctx)
cancel() // сигнал остановки
Способ 2: done-канал
done := make(chan struct{})
go func() {
for {
select {
case <-done:
return
case job := <-jobs:
process(job)
}
}
}()
close(done) // все читающие из done разблокируются
close(done) — мощный broadcast: все горутины, слушающие этот канал, получат сигнал одновременно. Context под капотом делает то же самое.