Ответ
Строго говоря, в Go существует только один вид горутин. Горутина — это легковесный поток исполнения, управляемый планировщиком Go (Go scheduler), а не операционной системой. Все горутины создаются и работают одинаково с точки зрения рантайма.
Однако на практике горутины можно классифицировать по их роли, состоянию или жизненному циклу в приложении. Это помогает лучше понимать архитектуру конкурентной программы.
Классификация по роли и состоянию:
-
Основная горутина (Main goroutine)
- Это горутина, в которой выполняется функция
main()
. Она запускается автоматически при старте программы. - Её завершение приводит к немедленному завершению всей программы, даже если другие горутины еще не закончили свою работу.
- Это горутина, в которой выполняется функция
-
Рабочие горутины (Worker goroutines)
- Это наиболее распространенный тип. Они запускаются с помощью ключевого слова
go
для выполнения конкретной задачи конкурентно (например, обработка HTTP-запроса, вычисление данных, работа с файлами).func main() { var wg sync.WaitGroup wg.Add(1) // Запуск рабочей горутины go func() { defer wg.Done() fmt.Println("Я — рабочая горутина") }() wg.Wait() // Ожидаем завершения }
- Это наиболее распространенный тип. Они запускаются с помощью ключевого слова
-
Горутины в состоянии ожидания (Blocking goroutines)
- Горутины, которые заблокированы в ожидании какого-либо события: I/O операции (сеть, диск), чтение из канала, ожидание мьютекса или таймера.
- Планировщик Go эффективно управляет ими, не блокируя поток ОС, а переключая на выполнение другую готовую горутину.
-
"Утёкшие" горутины (Leaked goroutines)
- Это горутины, которые никогда не завершат свое выполнение из-за ошибки в логике. Они продолжают существовать и потреблять память до конца работы программы.
- Частая причина утечки: горутина блокируется при отправке или чтении из канала, из которого никто никогда не прочитает или в который никто никогда не запишет.
// Пример утечки: горутина будет вечно ждать, // так как из канала ch никто не читает. ch := make(chan int) go func() { ch <- 1 // Блокировка навсегда }() // time.Sleep(time.Second) // Если раскомментировать, программа завершится, а горутина утечет
Таким образом, хотя технически все горутины одинаковы, понимание их ролей и состояний критически важно для написания корректных и эффективных конкурентных программ на Go.