Каналы в Go — это интересная и поначалу достаточно сложная для понимания концепция.
Если вы пришли из традиционных языков, таких как Java, то вы, скорее всего, использовали потоки с мьютексами или асинхронные очереди вроде Apache Kafka для организации взаимодействия между разными частями программы.
Синтаксис каналов может показаться странным, а семантика — расплывчатой, но они становятся понятнее, если воспринимать их как конкурентные очереди.
Канал в Go — это просто очередь, через которую можно передавать данные.
Если вы записываете в канал — это эквивалентно добавлению элемента в очередь.
Если вы читаете из канала — вы извлекаете первый элемент из очереди.
Очередь работает по принципу FIFO (первым пришёл — первым вышел).
У каналов множество применений. Например, представьте, что у вас есть HTTP-обработчик, и после завершения его работы вы хотите запустить дополнительную вычислительную задачу. Вы могли бы использовать асинхронную очередь для запуска workflow, а можете — канал.
В коде вы просто записываете значение в канал, например
Каналы безопасны для конкурентного чтения и записи — для записи в канал не нужен мьютекс.
Вы можете контролировать, сколько сигналов канал может буферизовать, указывая размер буфера при создании через
Можно создать канал, принимающий единичный сигнал (например, сигнал для закрытия базы данных), или буферизированный канал, в который несколько горутин записывают результаты своей работы.
Если количество горутин, пытающихся записать в канал, превышает его ёмкость, то лишние горутины будут блокироваться (то есть ждать), пока данные не будут считаны и не освободится место.
Из-за такого блокирующего поведения каналы иногда используют в качестве семафоров (хотя для этого существуют специализированные пакеты, которые лучше использовать вместо каналов).
По сути, каналы — это отличный способ организации взаимодействия между последовательными процессами, что и составляет суть модели конкурентности CSP (Communicating Sequential Processes) в Go.
Вот пример кода, показывающий мощь каналов. В Go существует возможность подписаться на сигналы операционной системы через канал.
Например, если программа завершается, вызывает панику, прерывается или останавливается — мы можем получить сообщение об этом через канал и корректно завершить работу сервера (записать состояние в лог, закрыть подключения к БД, завершить файловые операции и т. д.).
👉 @juniorGolang | #tip
Если вы пришли из традиционных языков, таких как Java, то вы, скорее всего, использовали потоки с мьютексами или асинхронные очереди вроде Apache Kafka для организации взаимодействия между разными частями программы.
Синтаксис каналов может показаться странным, а семантика — расплывчатой, но они становятся понятнее, если воспринимать их как конкурентные очереди.
Канал в Go — это просто очередь, через которую можно передавать данные.
Если вы записываете в канал — это эквивалентно добавлению элемента в очередь.
Если вы читаете из канала — вы извлекаете первый элемент из очереди.
Очередь работает по принципу FIFO (первым пришёл — первым вышел).
У каналов множество применений. Например, представьте, что у вас есть HTTP-обработчик, и после завершения его работы вы хотите запустить дополнительную вычислительную задачу. Вы могли бы использовать асинхронную очередь для запуска workflow, а можете — канал.
В коде вы просто записываете значение в канал, например
struct{user userID; data interface{}}, и это может послужить триггером для запуска другой вычислительной задачи.Каналы безопасны для конкурентного чтения и записи — для записи в канал не нужен мьютекс.
Вы можете контролировать, сколько сигналов канал может буферизовать, указывая размер буфера при создании через
make (например, userChan := make(chan interface{}, capacity)).Можно создать канал, принимающий единичный сигнал (например, сигнал для закрытия базы данных), или буферизированный канал, в который несколько горутин записывают результаты своей работы.
Если количество горутин, пытающихся записать в канал, превышает его ёмкость, то лишние горутины будут блокироваться (то есть ждать), пока данные не будут считаны и не освободится место.
Из-за такого блокирующего поведения каналы иногда используют в качестве семафоров (хотя для этого существуют специализированные пакеты, которые лучше использовать вместо каналов).
По сути, каналы — это отличный способ организации взаимодействия между последовательными процессами, что и составляет суть модели конкурентности CSP (Communicating Sequential Processes) в Go.
Вот пример кода, показывающий мощь каналов. В Go существует возможность подписаться на сигналы операционной системы через канал.
Например, если программа завершается, вызывает панику, прерывается или останавливается — мы можем получить сообщение об этом через канал и корректно завершить работу сервера (записать состояние в лог, закрыть подключения к БД, завершить файловые операции и т. д.).
Please open Telegram to view this post
VIEW IN TELEGRAM
❤6👍4
https://github.com/thevxn/xilt
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Большая актуальная базу бесплатных API, которая обновляется ежедневно
Тут собрано аж 363 бесплатных API на все случаи жизни: от игр и погоды до финансов и здоровья.
Алгоритмы присваивают рейтинг каждому API на основе надежности, частоты ошибок и времени отклика
Если API перестает работать или становится платным, он теряет рейтинг и удаляется с сайта
Переходите и смотрите сами: https://www.freepublicapis.com/
👉 @juniorGolang | #ресурсы
Тут собрано аж 363 бесплатных API на все случаи жизни: от игр и погоды до финансов и здоровья.
Алгоритмы присваивают рейтинг каждому API на основе надежности, частоты ошибок и времени отклика
Если API перестает работать или становится платным, он теряет рейтинг и удаляется с сайта
Переходите и смотрите сами: https://www.freepublicapis.com/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤3
Самостоятельно размещаемая альтернатива Google Analytics, реализованная на Go
https://github.com/vinceanalytics/vince
👉 @juniorGolang | #ресурсы
https://github.com/vinceanalytics/vince
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤1
Принёс шпаргалку с 12 командами Git, которые «должен знать каждый разраб»
Сохраняем и пользуемся
К слову, Git на днях отметил своё 20-летие — 7 апреля 2005 года Линус Торвальдс написал его всего за пару недель, чтобы заменить BitKeeper при разработке ядра Linux
С тех пор без Git не обходится почти ни один проект✌️
👉 @juniorGolang
1. git init – инициализация нового Git-репозитория в текущем каталоге.
2. git add – добавление изменений в индекс (staging area).
3. git commit – фиксация проиндексированных изменений с комментарием.
4. git push – отправка локальных изменений в удалённый репозиторий.
5. git pull – получение изменений из удалённого репозитория и их слияние с локальной веткой.
6. git remote – добавление, просмотр или удаление удалённого репозитория.
7. git branch – вывод списка веток, создание новой ветки и переключение на неё.
8. git fetch – загрузка изменений из удалённого репозитория без их слияния.
9. git checkout – переключение на указанную ветку.
10. git merge – слияние указанной ветки с текущей.
11. git status – отображение текущего состояния репозитория и неподтверждённых изменений.
12. git reset – откат текущей ветки до указанного коммита.
Сохраняем и пользуемся
К слову, Git на днях отметил своё 20-летие — 7 апреля 2005 года Линус Торвальдс написал его всего за пару недель, чтобы заменить BitKeeper при разработке ядра Linux
С тех пор без Git не обходится почти ни один проект
Please open Telegram to view this post
VIEW IN TELEGRAM
❤8👍5
Пакет Go, который декодирует
https://github.com/go-playground/form
👉 @juniorGolang | #ресурсы
url.Values в значения Go и кодирует значения Go в url.Values. Поддержка как массивов, так и полных отображенийhttps://github.com/go-playground/form
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - go-playground/form: :steam_locomotive: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual…
:steam_locomotive: Decodes url.Values into Go value(s) and Encodes Go value(s) into url.Values. Dual Array and Full map support. - go-playground/form
👍5
gRPC в Go: Потоковые RPC, перехватчики и метаданные
Это самое полное базовое руководство, охватывающее типы RPC, перехватчики, заголовки, трейлеры и многое другое
https://victoriametrics.com/blog/go-grpc-basic-streaming-interceptor/
👉 @juniorGolang | #cтатья
Это самое полное базовое руководство, охватывающее типы RPC, перехватчики, заголовки, трейлеры и многое другое
https://victoriametrics.com/blog/go-grpc-basic-streaming-interceptor/
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥2
https://github.com/epuerta9/codex-go
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4
Если вы хотите протестировать производительность своего Go-кода, вы можете написать несколько бенчмарк-тестов.
Они анализируют скорость выполнения и использование памяти различными функциями и блоками кода.
Здесь Педро показывает, как писать бенчмарк-тесты для ваших функций на Golang:
https://freecodecamp.org/news/how-to-write-benchmark-tests-for-your-golang-functions/
👉 @juniorGolang | #cтатья
Они анализируют скорость выполнения и использование памяти различными функциями и блоками кода.
Здесь Педро показывает, как писать бенчмарк-тесты для ваших функций на Golang:
https://freecodecamp.org/news/how-to-write-benchmark-tests-for-your-golang-functions/
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3👍2
Начиная с Go 1.8, стандартная библиотека
Этот метод обеспечивает "плавное" завершение работы сервера, поскольку он:
🔹 Немедленно прекращает приём новых подключений
🔹 Сохраняет существующие подключения активными до завершения всех текущих запросов
🔹 Предоставляет контекст для управления таймаутом на завершение "висящих" запросов
🔹 Завершается только после обработки всех находящихся в процессе выполнения запросов
🔹 Предотвращает утечки подключений при завершении работы приложения
Без корректного завершения, принудительное завершение работы сервера может привести к обрыву активных запросов, ошибкам на стороне клиента и потенциальной неконсистентности данных.
Метод
👉 @juniorGolang | #tip
http.Server включает метод Shutdown, который критически важен для корректного завершения работы веб-сервисов.Этот метод обеспечивает "плавное" завершение работы сервера, поскольку он:
Без корректного завершения, принудительное завершение работы сервера может привести к обрыву активных запросов, ошибкам на стороне клиента и потенциальной неконсистентности данных.
Метод
Shutdown элегантно решает эту проблему. Ниже приведена полноценная реализация, демонстрирующая обработку нескольких сигналов ОС для плавного завершения работы:Please open Telegram to view this post
VIEW IN TELEGRAM
❤14👍9
This media is not supported in your browser
VIEW IN TELEGRAM
Лёгкая очередь сообщений, реализованная на Go, с поддержкой SQLite, PostgreSQL и ORM в качестве постоянного хранилища
https://github.com/ixugo/nsqite/blob/master/README.md
👉 @juniorGolang | #ресурсы
https://github.com/ixugo/nsqite/blob/master/README.md
Please open Telegram to view this post
VIEW IN TELEGRAM
👍8❤1
При разработке приложений, использующих LLM API, таких как OpenAI или Anthropic, вы быстро упрётесь в лимиты запросов при масштабной обработке. Пакет
🔹 Реализует лимитирование скорости на основе алгоритма token bucket с точной настройкой
🔹 Поддерживает ожидание с учётом контекста и возможностью отмены
🔹 Эффективно обрабатывает всплески нагрузки благодаря настраиваемому размеру «ведра»
🔹 Органично интегрируется с моделью конкурентности Go
Алгоритм token bucket особенно хорошо подходит для LLM‑API. Каждый запрос потребляет один токен из «бакета», который пополняется с заданной скоростью. Если «бакет» пуст, запросы ожидают появления токенов вместо того, чтобы сразу завершаться с ошибкой.
Выше приведён пример кода с неофициальным клиентом OpenAI и использованием пакета
👉 @juniorGolang | #tip
rate из https://golang.org — хорошее решение этой проблемы, так как он:Алгоритм token bucket особенно хорошо подходит для LLM‑API. Каждый запрос потребляет один токен из «бакета», который пополняется с заданной скоростью. Если «бакет» пуст, запросы ожидают появления токенов вместо того, чтобы сразу завершаться с ошибкой.
Выше приведён пример кода с неофициальным клиентом OpenAI и использованием пакета
ratePlease open Telegram to view this post
VIEW IN TELEGRAM
👍7❤1
https://github.com/sesopenko/genericpubsub
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3
Если вы обрабатываете HTTP-запросы на Go, сжатие gzip является важным инструментом для снижения потребления трафика и ускорения отклика. Пакет
При реализации gzip-сжатия в веб-серверах:
🔹 Всегда проверяйте заголовок
🔹 Устанавливайте корректный заголовок ответа
🔹 Избегайте сжатия уже сжатых форматов (например, изображений, видео)
🔹 Используйте
Вот пример реализации с использованием паттерна middleware.
👉 @juniorGolang | #tip
encoding/gzip упрощает реализацию, но есть некоторые подводные камни, о которых стоит помнить.При реализации gzip-сжатия в веб-серверах:
Accept-Encoding перед применением сжатияContent-Encodingsync.Pool для повторного использования gzip-писателей и повышения производительностиВот пример реализации с использованием паттерна middleware.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14❤2
https://github.com/boozec/rahanna
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10❤1
Дженерики в Go: Ваш дружелюбный гид по повторно используемому коду
В этом гайде рассказывается, что такое дженерики, как их использовать и зачем они нужны
👉 Читать
👉 @juniorGolang | #cтатья
В этом гайде рассказывается, что такое дженерики, как их использовать и зачем они нужны
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍5
https://github.com/go-simpler/sloglint
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
GitHub - go-simpler/sloglint: 🪵 Ensure consistent code style when using log/slog
🪵 Ensure consistent code style when using log/slog - go-simpler/sloglint
❤9
Сигнал SIGHUP для перезагрузки конфигурации
SIGHUP — это сигнал, находящийся на стыке двух миров. Он возник из-за физического «обрыва» соединения с терминалом, и его изначальное значение — потеря управляющего терминала — актуально до сих пор.
Многие приложения, включая приложения на Go (по умолчанию), обрабатывают три сигнала для завершения работы: SIGTERM, SIGINT и SIGHUP. Среди них SIGHUP несет дополнительные нюансы и сегодня может иметь меньшее значение.
По определению:
Но что именно представляет собой «управляющий терминал»?
👉 Читать далее
👉 @juniorGolang | #cтатья
SIGHUP — это сигнал, находящийся на стыке двух миров. Он возник из-за физического «обрыва» соединения с терминалом, и его изначальное значение — потеря управляющего терминала — актуально до сих пор.
Многие приложения, включая приложения на Go (по умолчанию), обрабатывают три сигнала для завершения работы: SIGTERM, SIGINT и SIGHUP. Среди них SIGHUP несет дополнительные нюансы и сегодня может иметь меньшее значение.
По определению:
SIGHUP («signal hang up») — это сигнал, отправляемый процессу при закрытии его управляющего терминала. — Википедия
Но что именно представляет собой «управляющий терминал»?
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤4
С помощью Go можно создавать и запускать последовательные программы, которые обмениваются данными друг с другом через каналы.
Однако поведение каналов по умолчанию — блокирующее, если нет данных для чтения:
Это полезно в сценариях, где нужно дождаться сигнала перед выполнением каких-либо действий (например, для корректного завершения работы). Но иногда требуется, чтобы часть программы одновременно слушала несколько каналов.
Если выполнение блокируется на первом канале, как оно узнает о сообщении во втором? Решением является мультиплексирование каналов, и в Go это делается с помощью ключевого слова
Ключевое слово
Вы можете явно блокировать выполнение или использовать
Предположим, у вас есть фоновый воркер, который, получив данные из очереди, должен выполнить некоторую операцию. Также вы хотите обрабатывать сигналы отмены и периодически чистить ресурсы, поскольку воркер работает в фоне.
В приведённом примере мы мультиплексируем каналы, чтобы добиться всего этого:
В первом
Внутри этого блока создаётся
Внутри
После завершения обработки (успешной или по тайм-ауту) вызывается
Далее мы пытаемся отправить результат в канал результатов, но с дополнительной защитой — мы не хотим блокироваться, если получатель не успевает обрабатывать данные.
Снова используется
Второй
Третий
Такой шаблон элегантно решает сразу несколько задач: обработку задач, учёт тайм-аутов, корректное завершение, доставку результатов и регулярное обслуживание — при этом предотвращая утечки ресурсов.
👉 @juniorGolang
Однако поведение каналов по умолчанию — блокирующее, если нет данных для чтения:
<-channel (будет ожидать, пока не появятся данные)Это полезно в сценариях, где нужно дождаться сигнала перед выполнением каких-либо действий (например, для корректного завершения работы). Но иногда требуется, чтобы часть программы одновременно слушала несколько каналов.
Если выполнение блокируется на первом канале, как оно узнает о сообщении во втором? Решением является мультиплексирование каналов, и в Go это делается с помощью ключевого слова
select.Ключевое слово
select в Go синтаксически похоже на оператор switch, но используется для мультиплексирования каналов, то есть для одновременного прослушивания нескольких каналов. Каждый case — это операция с каналом, при выполнении которой исполняется соответствующий блок кода (чтение из канала или запись в него).Вы можете явно блокировать выполнение или использовать
default-ветку, чтобы продолжить выполнение без блокировки.Предположим, у вас есть фоновый воркер, который, получив данные из очереди, должен выполнить некоторую операцию. Также вы хотите обрабатывать сигналы отмены и периодически чистить ресурсы, поскольку воркер работает в фоне.
В приведённом примере мы мультиплексируем каналы, чтобы добиться всего этого:
В первом
case мы получаем данные из очереди для дальнейшей обработки. Если канал закрыт — выходим из воркера.Внутри этого блока создаётся
context с тайм-аутом 30 секунд, который передаётся в функцию, обрабатывающую задачу с учётом тайм-аута. Это критически важно — так ни одна задача не сможет бесконечно блокировать воркер.Внутри
processWithTimeout() запускается горутина, выполняющая основную задачу, в то время как основная функция ожидает либо завершения работы, либо срабатывания тайм-аута. Для этого используется буферизированный канал для получения результата и select-оператор для обработки возможных ситуаций с тайм-аутом.После завершения обработки (успешной или по тайм-ауту) вызывается
cancel(), чтобы освободить ресурсы, связанные с контекстом. Даже если операция завершилась по тайм-ауту, явный вызов cancel() — это хорошая практика в Go для корректной очистки ресурсов.Далее мы пытаемся отправить результат в канал результатов, но с дополнительной защитой — мы не хотим блокироваться, если получатель не успевает обрабатывать данные.
Снова используется
select с default-веткой: если канал результатов переполнен, логируется предупреждение, и воркер сразу переходит к следующей задаче без ожидания. Такой неблокирующий подход предотвращает зависание воркера и позволяет ему продолжать работу даже при перегрузке получателя.Второй
case в основном select-блоке обрабатывает корректное завершение работы — при отмене родительского контекста воркер очищает ресурсы и завершает выполнение.Третий
case реализует периодическую проверку состояния (health check) каждые 5 минут бездействия. Это необходимо для выполнения обслуживающих задач, таких как очистка устаревших соединений, даже если нет новых задач.Такой шаблон элегантно решает сразу несколько задач: обработку задач, учёт тайм-аутов, корректное завершение, доставку результатов и регулярное обслуживание — при этом предотвращая утечки ресурсов.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤6🔥3
Вышел Pion WebRTC v4.1.0 — стабильная поддержка полного AV1, передача больших сообщений через DataChannels и RTP-пейлоадер для H.265
https://github.com/pion/webrtc/releases/tag/v4.1.0
👉 @juniorGolang
https://github.com/pion/webrtc/releases/tag/v4.1.0
Please open Telegram to view this post
VIEW IN TELEGRAM
GitHub
Release v4.1.0 · pion/webrtc
Pion v4.1.0
New release schedule – a fresh minor version will ship on the last weekend of every month.
AV1 support is complete and stable.
Data Channels now handle payloads larger than 65 535 byte...
New release schedule – a fresh minor version will ship on the last weekend of every month.
AV1 support is complete and stable.
Data Channels now handle payloads larger than 65 535 byte...
👍9❤2
Golang sync.Pool — не серебряная пуля
Когда речь заходит об оптимизации производительности в Go, sync.Pool часто выглядит как заманчивое решение. Он обещает сократить количество аллокаций памяти и снизить нагрузку на сборщик мусора за счёт повторного использования объектов. Но всегда ли это правильный выбор? Давайте углубимся в эту интересную тему.
👉 Читать
👉 @juniorGolang
Когда речь заходит об оптимизации производительности в Go, sync.Pool часто выглядит как заманчивое решение. Он обещает сократить количество аллокаций памяти и снизить нагрузку на сборщик мусора за счёт повторного использования объектов. Но всегда ли это правильный выбор? Давайте углубимся в эту интересную тему.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤2🌭1