Какие паттерны конкурентной работы (concurrency) в Go вы знаете?

Ответ

Go продвигает философию CSP (Communicating Sequential Processes), где основной принцип — «не обменивайтесь данными через общую память, а делитесь памятью через обмен данными». Это достигается с помощью горутин и каналов. Основные паттерны:

  1. Worker Pool (Пул воркеров)

    • Описание: Создается фиксированное количество горутин-воркеров для обработки задач из общего канала. Это позволяет контролировать уровень параллелизма и избежать создания неограниченного числа горутин.
    • Пример:
      
      jobs := make(chan int, 100)
      results := make(chan int, 100)

    // Запуск 3 воркеров for w := 1; w <= 3; w++ { go worker(w, jobs, results) }

  2. Fan-out / Fan-in

    • Описание: Один производитель данных распределяет (fan-out) работу между несколькими горутинами-обработчиками. Затем результаты от всех обработчиков собираются (fan-in) в один канал.
  3. Pipeline (Конвейер)

    • Описание: Цепочка этапов обработки, где каждый этап — это горутина, принимающая данные из входящего канала и отправляющая результат в исходящий. Позволяет эффективно распараллеливать последовательные задачи.
    • Пример этапа:
      func square(in <-chan int) <-chan int {
      out := make(chan int)
      go func() {
          defer close(out)
          for n := range in {
              out <- n * n
          }
      }()
      return out
      }
  4. Generator (Генератор)

    • Описание: Функция, которая запускает горутину и возвращает канал. Горутина генерирует данные и отправляет их в этот канал, скрывая детали реализации от потребителя.
  5. Context для отмены и таймаутов

    • Описание: Использование пакета context для передачи сигналов отмены, дедлайнов и таймаутов вниз по стеку вызовов в другие горутины. Ключевой паттерн для graceful shutdown.
  6. Mutex / RWMutex для защиты общих данных

    • Описание: Классический паттерн для защиты разделяемой памяти от гонок данных (race conditions), когда использование каналов нецелесообразно. sync.Mutex для эксклюзивного доступа, sync.RWMutex для ситуаций с частыми чтениями и редкими записями.

Ответ 18+ 🔞

Ну, слушай, тут у нас Go, как хулиган с философией, подходит и говорит: «Забудь про общую память, как про вчерашний день, блядь! Вместо этого — делишься памятью через обмен данными». И делает он это через горутины и каналы, эти ёбаные трубы для сообщений. Вот основные паттерны, без которых ты как без рук, точнее, как без каналов.

  1. Worker Pool (Пул воркеров)

    • Суть: Чтобы не порождать горутин, как сумасшедший, до овердохуища, ты создаёшь их фиксированную банду. Они сидят, ждут задачку из общего канала, как голодные псы, и жрут работу. Контроль над параллелизмом — твой, а не у чёрта на рогах.
    • Кусок кода, смотри:
      
      jobs := make(chan int, 100)
      results := make(chan int, 100)

    // Запускаем трёх работяг for w := 1; w <= 3; w++ { go worker(w, jobs, results) }

  2. Fan-out / Fan-in

    • Суть: Один чувак нагенерил кучу данных (fan-out) и раскидал всем остальным на обработку. А те, обработав, скидывают результаты обратно в одну общую кучу (fan-in). Как на стройке: один кирпичи подвозит, десять кладут.
  3. Pipeline (Конвейер)

    • Суть: Представь заводскую линию. Один этап — одна горутина. Принял из предыдущей трубы, обработал, выплюнул в следующую. Красота, а не жизнь. Позволяет размазать последовательные задачи по ядрам.
    • Вот, например, этап «возвести в квадрат»:
      func square(in <-chan int) <-chan int {
      out := make(chan int)
      go func() {
          defer close(out)
          for n := range in {
              out <- n * n
          }
      }()
      return out
      }
  4. Generator (Генератор)

    • Суть: Хитрая, блядь, функция. Запускает внутри себя горутину-невидимку, которая тихонечко, как мышка, генерит данные в канал. А сама функция тебе этот канал возвращает. Потребитель даже не в курсе, откуда там данные берутся, ему главное — получать.
  5. Context для отмены и таймаутов

    • Суть: А это, сука, самое важное для взрослых дяденек. Чтобы твои горутины не висели вечно, если что-то пошло не так. Через context ты можеть крикнуть всем вниз по цепочке: «Всё, пиздец, закругляйтесь!» Или сказать: «У тебя 2 секунды, иначе нахуй». Базовый паттерн для культурного завершения работы, а не для вырубания сервера топором.
  6. Mutex / RWMutex для защиты общих данных

    • Суть: Ну а тут, ебать мои старые костыли, классика жанра. Иногда каналы — это как приехать на такси в туалет, слишком наворочено. Проще поставить замок на дверь. sync.Mutex — это когда один заходит, остальные ждут. sync.RWMutex — это когда много народу может смотреть (читать), но писать может только один, и то когда все выйдут. Чтобы не было гонок данных, этой ёбаной чехарды в памяти.

Вот так-то, дружище. Вроде бы и язычок простой, а паттерны — как у взрослых, только со своими, гоферскими, приколами.