В каких случаях целесообразно применять конкурентность в Go (горутины и каналы)? Приведите примеры.

Ответ

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

  1. I/O-bound операции (работа с сетью, диском). Это основной и самый частый кейс. Пока одна горутина ждет ответа от базы данных, API или файловой системы, другие горутины могут выполняться, эффективно утилизируя процессор.

    Пример: одновременная загрузка данных с нескольких URL.

    func main() {
        urls := []string{"https://site1.com", "https://site2.com", "https://site3.com"}
        var wg sync.WaitGroup
    
        for _, url := range urls {
            wg.Add(1) // Увеличиваем счетчик WaitGroup
            go func(u string) {
                defer wg.Done() // Уменьшаем счетчик по завершении горутины
                http.Get(u)
                fmt.Printf("Fetched %sn", u)
            }(url)
        }
    
        wg.Wait() // Ожидаем завершения всех горутин
        fmt.Println("All fetches complete.")
    }
  2. CPU-bound задачи, которые можно распараллелить. Задачи, требующие интенсивных вычислений (обработка изображений, математические расчеты), могут быть разделены на подзадачи и выполнены параллельно на многоядерных процессорах. Переменная runtime.GOMAXPROCS контролирует, сколько потоков ОС могут одновременно выполнять Go-код.

  3. Фоновые процессы. Задачи, которые должны работать в фоне, не блокируя основной поток приложения. Например, периодический сбор метрик, логирование, очистка кэша.

Когда конкурентность может навредить:

  • Для очень простых и быстрых операций: накладные расходы на создание горутины и синхронизацию могут превысить выгоду.
  • Задачи с сильной зависимостью по данным: если задачи не независимы и требуют сложной синхронизации, код может стать запутанным и подверженным состоянию гонки (data race).
  • В коде, где важна строгая последовательность выполнения: конкурентность по своей природе не гарантирует порядок выполнения.