Какие существуют виды или классификации горутин в Go?

Ответ

Строго говоря, в Go существует только один вид горутин. Горутина — это легковесный поток исполнения, управляемый планировщиком Go (Go scheduler), а не операционной системой. Все горутины создаются и работают одинаково с точки зрения рантайма.

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

Классификация по роли и состоянию:

  1. Основная горутина (Main goroutine)

    • Это горутина, в которой выполняется функция main(). Она запускается автоматически при старте программы.
    • Её завершение приводит к немедленному завершению всей программы, даже если другие горутины еще не закончили свою работу.
  2. Рабочие горутины (Worker goroutines)

    • Это наиболее распространенный тип. Они запускаются с помощью ключевого слова go для выполнения конкретной задачи конкурентно (например, обработка HTTP-запроса, вычисление данных, работа с файлами).
      func main() {
      var wg sync.WaitGroup
      wg.Add(1)
      // Запуск рабочей горутины
      go func() {
          defer wg.Done()
          fmt.Println("Я — рабочая горутина")
      }()
      wg.Wait() // Ожидаем завершения
      }
  3. Горутины в состоянии ожидания (Blocking goroutines)

    • Горутины, которые заблокированы в ожидании какого-либо события: I/O операции (сеть, диск), чтение из канала, ожидание мьютекса или таймера.
    • Планировщик Go эффективно управляет ими, не блокируя поток ОС, а переключая на выполнение другую готовую горутину.
  4. "Утёкшие" горутины (Leaked goroutines)

    • Это горутины, которые никогда не завершат свое выполнение из-за ошибки в логике. Они продолжают существовать и потреблять память до конца работы программы.
    • Частая причина утечки: горутина блокируется при отправке или чтении из канала, из которого никто никогда не прочитает или в который никто никогда не запишет.
      // Пример утечки: горутина будет вечно ждать, 
      // так как из канала ch никто не читает.
      ch := make(chan int)
      go func() {
      ch <- 1 // Блокировка навсегда
      }()
      // time.Sleep(time.Second) // Если раскомментировать, программа завершится, а горутина утечет

Таким образом, хотя технически все горутины одинаковы, понимание их ролей и состояний критически важно для написания корректных и эффективных конкурентных программ на Go.