Запуск горутины без управления её завершением



Запуск горутины (go func()) без механизма её завершения может привести к утечкам ресурсов и непредсказуемому поведению приложения. Особенно это критично для долгоживущих приложений или сервисов с высоким уровнем конкурентности



Пример:

func process() {

go func() {

// Выполняется какая-то длительная задача

time.Sleep(5 * time.Second)

fmt.Println("Горутина завершена")

}()

}


Если процесс завершится раньше, горутина продолжит выполнение, что может привести к утечке памяти или нарушению логики программы.



Как избежать ошибки?



1️⃣ Используйте контекст (context.Context) для управления временем жизни:

func process(ctx context.Context) {

go func() {

select {

case <-ctx.Done():

fmt.Println("Горутина остановлена")

return

case <-time.After(5 * time.Second):

fmt.Println("Задача выполнена")

}

}()

}

}



func main() {

ctx, cancel := context.WithCancel(context.Background())

process(ctx)



// Завершаем процесс через 2 секунды

time.Sleep(2 * time.Second)

cancel()

time.Sleep(3 * time.Second) // Ждём, чтобы увидеть результат

}




2️⃣ Используйте sync.WaitGroup для координации завершения:

func process(wg *sync.WaitGroup) {

defer wg.Done()

time.Sleep(5 * time.Second)

fmt.Println("Задача завершена")

}



func main() {

var wg sync.WaitGroup

wg.Add(1)

go process(&wg)



wg.Wait() // Ждём завершения всех горутин

fmt.Println("Все задачи завершены")

}




Почему это важно?



Бесконтрольные горутины приводят к непредсказуемым утечкам памяти и нагружают приложение. Это одна из самых частых проблем в Go-программах, которую сложно диагностировать на поздних этапах.



👉 @juniorGolang