{}const=>[]async()letfn</>var
РазработкаBackendОбзор

Горутины и каналы в Go: параллельность, которая не ломает мозг (ну почти 😄)

Разбираем, как в Go работает параллельность: что такое горутины, каналы и как с их помощью писать быстрый и понятный код. Без сложной теории — только практика и реальные примеры.

К

Кодик

Автор

4 мин чтения

🚀 Почему Go так любят за параллельность?

В большинстве языков параллельность выглядит как отдельный квест: потоки, блокировки, синхронизация, дедлоки, слёзы, кофе, ещё слёзы.

А в Go всё начинается с одного короткого слова:

go

Да, буквально. Хочешь запустить функцию параллельно? Просто добавляешь go перед вызовом. Это и есть одна из главных причин, почему Go так любят для backend-разработки, микросервисов, парсеров, API и всего, где нужно делать много задач одновременно.

🔥 100 000+ учеников уже с нами

Устал читать теорию?
Пора кодить!

Кодик — приложение, где ты учишься программировать через практику. AI-наставник, интерактивные уроки, реальные проекты.

🤖 AI 24/7
🎓 Сертификаты
💰 Бесплатно
🚀 Начать учиться
Присоединились сегодня

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

Горутина — это лёгкая задача, которая выполняется параллельно с остальным кодом. Можно думать о ней как о маленьком работнике, которого Go запускает выполнять функцию.

Пример:

package main

import (
    "fmt"
    "time"
)

func sayHello() {
    fmt.Println("Привет из горутины!")
}

func main() {
    go sayHello()

    time.Sleep(time.Second)
    fmt.Println("main завершился")
}

Здесь sayHello() запускается отдельно от основной функции main(). Но есть важный момент: если main завершится раньше, программа закроется вместе со всеми горутинами.

Поэтому в примере стоит time.Sleep. Это не лучший способ ждать горутину, но для первого знакомства — норм.

😄 Горутины — это не магия, а очень удобный инструмент

Представь, что тебе нужно выполнить три задачи:

  • загрузить данные пользователя;

  • получить список заказов;

  • запросить настройки профиля.

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

А с горутинами можно отправить три задачи одновременно. Это уже не очередь, а нормальный такой многопоточный фудкорт.

🧪 Пример: несколько задач одновременно

package main

import (
    "fmt"
    "time"
)

func task(name string) {
    for i := 1; i <= 3; i++ {
        fmt.Println(name, "шаг", i)
        time.Sleep(500 * time.Millisecond)
    }
}

func main() {
    go task("Задача A")
    go task("Задача B")

    time.Sleep(2 * time.Second)
}

Если запустить этот код, вывод будет перемешиваться: то работает задача A, то задача B.

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

🔌 Но как горутинам обмениваться данными?

Запустить функцию параллельно — это половина дела. Вторая половина — понять, как получить результат обратно.

И вот тут в Go появляются каналы.

Канал — это специальный механизм, через который горутины могут передавать данные друг другу. Можно представить его как трубу:

  • одна горутина кладёт данные в канал;

  • другая горутина забирает данные из канала.

📦 Создаём канал

ch := make(chan string)

Это канал, через который можно передавать строки.

Отправка данных:

ch <- "готово"

Получение данных:

result := <-ch

🧪 Пример с каналом

package main

import "fmt"

func worker(ch chan string) {
    ch <- "Задача выполнена"
}

func main() {
    ch := make(chan string)

    go worker(ch)

    result := <-ch
    fmt.Println(result)
}

Что здесь происходит:

  • main создаёт канал;

  • запускает worker в отдельной горутине;

  • worker отправляет результат в канал;

  • main получает результат и выводит его.

Красота. Без лишней драмы.

🧠 Главная идея Go:

Не заставляй горутины драться за общую память. Лучше пусть они общаются через каналы.

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

🔥 Реальная задача: параллельная загрузка данных

Теперь ближе к жизни.

Допустим, у нас есть несколько URL, и мы хотим загрузить данные с каждого. Если делать запросы по очереди, будет медленно.

Поэтому запустим загрузку параллельно.

package main

import (
    "fmt"
    "time"
)

func fetch(url string, ch chan string) {
    time.Sleep(time.Second)
    ch <- "Данные получены с " + url
}

func main() {
    urls := []string{
        "https://api.example.com/users",
        "https://api.example.com/orders",
        "https://api.example.com/settings",
    }

    ch := make(chan string)

    for _, url := range urls {
        go fetch(url, ch)
    }

    for i := 0; i < len(urls); i++ {
        result := <-ch
        fmt.Println(result)
    }
}

Здесь каждая загрузка запускается в отдельной горутине. Потом мы столько раз читаем из канала, сколько задач запустили.

В итоге все запросы выполняются одновременно, а программа получает результаты по мере готовности.

🧩 Когда использовать горутины?

Горутины хорошо подходят, когда нужно:

  • делать несколько HTTP-запросов одновременно;

  • обрабатывать много файлов;

  • парсить страницы;

  • запускать фоновые задачи;

  • строить быстрые backend-сервисы;

  • обрабатывать очереди сообщений.

Но не нужно использовать горутины просто потому, что “ну Go же”. Если задача простая и выполняется быстро, параллельность может только усложнить код.

💙 Где прокачивать Go и другие языки?

Если хочется не просто читать статьи, а реально практиковаться, загляни в приложение Кодик.

Там можно учить программирование через понятные уроки, практические задания и постепенное усложнение без ощущения, что тебя бросили в бассейн с акулой и документацией.

А ещё у Кодика есть телеграм-сообщество, где выходят полезные посты, разборы и идеи для повторения программирования в удобном формате. Это хороший способ не выпадать из обучения и регулярно возвращаться к практике.

🎯 Итог

Горутины и каналы — это одна из самых сильных сторон Go.

С их помощью можно:

  • запускать задачи параллельно;

  • ускорять загрузку данных;

  • обрабатывать несколько процессов одновременно;

  • писать понятный конкурентный код.

Главное — не воспринимать параллельность как магию. Горутина — это задача. Канал — это способ передать данные.

Всё. Уже не так страшно.

А если после этого ты впервые запустишь 10 горутин и всё реально сработает — поздравляем, ты официально сделал шаг в Go-разработку без боли 😄


А ты уже пробовал горутины в Go? Напиши, что сложнее всего: понять каналы, дождаться результата или не устроить дедлок?

🎯Хватит откладывать

Понравилась статья?
Пора применять на практике!

В Кодик ты не просто читаешь — ты сразу пишешь код. Теория + практика = реальный скилл.

Мгновенная практика
🧠AI объяснит код
🏆Сертификат

Без регистрации • Без карты