Назад к урокам

Горутины (Goroutines) в Go

Урок объясняет принципы работы горутин: конкурентный запуск функций, особенности выполнения, примеры с замыканиями, разделяемые переменные и ключевые свойства конкурентности в Go.

Начинающий10 min

🟦 Goroutines в Go

Горутины - это лёгкие конкурентные задачи, которые позволяют выполнять функции параллельно или асинхронно. Они создаются с помощью ключевого слова go и работают сверхэффективно благодаря встроенному планировщику Go.


🚀 Что такое горутина?

Горутина - это функция, запускаемая в отдельном конкурентном контексте:

go myFunc()

Особенности:

  • выполнение вызывающей функции НЕ останавливается;
  • горутина продолжает работать независимо;
  • Go сам решает - выполнять параллельно или асинхронно;
  • горутина завершается только после завершения своей функции.

📌 Пример: базовый запуск горутины

func count(amount int) {
    for i := 1; i <= amount; i++ {
        time.Sleep(100 * time.Millisecond)
        fmt.Println(i)
    }
}

func main() {
    go count(5)

    fmt.Println("wait for goroutine")
    time.Sleep(1000 * time.Millisecond)
    fmt.Println("end program")
}

Ожидаемый вывод:

wait for goroutine
1
2
3
4
5
end program

Без Sleep программа завершилась бы раньше, чем горутина.


🧪 Пример: горутины + замыкания

Горутины могут запускать анонимные функции (замыкания), захватывая внешние переменные:

counter := 0

wait := func(ms time.Duration) {
    time.Sleep(ms * time.Millisecond)
    counter += 1
}

fmt.Println("Launching goroutines")
go wait(100)
go wait(900)
go wait(1000)

fmt.Println("Launched. Counter =", counter)
time.Sleep(1100 * time.Millisecond)
fmt.Println("Waited 1100ms. Counter =", counter)

Вывод:

Launching goroutines
Launched.    Counter = 0
Waited 1100ms. Counter = 3

🔍 Важно: Все горутины делят одну и ту же переменную counter.
Это может приводить к гонкам данных, если не использовать синхронизацию.


⚠️ Важные свойства горутин

  • Не блокируют вызывающую функцию
  • Запускаются мгновенно
  • Очень лёгкие - тысячи горутин стоят дешевле одного потока ОС
  • Могут использовать замыкания
  • Для общих данных требуется синхронизация (каналы, мьютексы)

🎯 Итоги

  • go myFunc() запускает конкурентное выполнение
  • Порядок выполнения недетерминирован
  • Захваченные замыкания разделяются между горутинами
  • Горутины - основа всей конкурентности Go