
Мы рассмотрим несколько примеров запуска goroutine и контроля их выполнения.
В golang есть отличный механизм для запуска параллельных потоков например:
package main import ( "log" "time" ) func job(duration time.Duration) { <-time.After(duration) log.Println("job done") } func main() { go func(){ job(time.Minute) }() }
Но как и любой механизм он не лишен недостатков, предыдущий пример может не завершить работу в goroutine при этом основной поток уже будет остановлен.
Нам уже необходимо будет ожидать выполнение процесса например при помощи `WaitGroup`
package main import ( "log" "sync" "time" ) func main() { wg := sync.WaitGroup{} wg.Add(1) go func() { defer wg.Done() job(time.Microsecond) }() wg.Wait() }
А что если нам надо чтобы процесс был запущен много раз, тогда получается
package main import ( "log" "time" ) func main() { go func() { for{ job(time.Minute) } }() }
В примерах я буду показывать только ключевые моменты, посмотреть пример полностью можно будет в Go Playground по ссылке.
Данный пример будет работать пока мы не завершим процесс принудительно. Но что если работу нужно завершить а только потом можно завершать весь процесс, это можно сделать например
package main import ( "context" "log" "time" ) func main() { ctx, cancel := context.WithTimeout(context.Background(),time.Microsecond) defer cancel() go func() { for{ select{ case <-ctx.Done(): return default: job(time.Microsecond/2) } } }() }
В этом случае мы управляем процессом с помощью пакета `context`, он может быть остановлен к примеру `graceful shutdown` но об этом в следующий раз.
Эта работа будет запускаться всегда как только завершится предыдущая, это встречается редко, обычно нам надо запускать обработку не чаще чем, изменим код и получится
package main import ( "context" "log" "time" ) func main() { go func() { for{ select{ case <-time.After(time.Microsecond): job(time.Microsecond/2) } } }() }
Выводы
Я привел несколько примеров как просто запускать выполнение фоновых операций параллельно, но это не все что может потребоваться. Обычно это вырастает в каждом проекте по своему, ведь это просто, потом разрастается ведь нам к примеру нужны будут еще метрики и запись логов, ведь процесс фоновый. Чтобы избежать повторения базового решения можно использовать пакет go-4devs/daemon, который уже все это делает и даже больше. Включая обработку завершения работ(jobs), завершения всех запущенных job и тп.