Golang Дайджест
8.15K subscribers
37 photos
1 file
185 links
Самое интересное из мира Go: новости, статьи, проекты, сервисы, изменения в языке и др.

Посты публикуются не часто - только самое важное, с чем я лично ознакомился.

Поэтому можно не мьютить канал =)

Обратная связь: @justskiv
Download Telegram
🧪 Сравнение инструментов для генерации моков

https://habr.com/ru/companies/avito/articles/939388/

Семён Эйгин из Авито (мейнтейнер minimock) сравнивает три популярных инструмента для генерации моков:

- mockery
- gomock
- minimock

Очевидно, автор предвзят, но статья всё равно интересная. Просто учитывайте это во время чтения.

Какие проблемы обсуждаются:

1. Типизация параметров

- mockery и gomock используют interface{} в ожиданиях: GetUser(1) интерпретируется как int вместо int64
- minimock генерирует строго типизированные методы: Expect(id int64)
- На практике: можно пропустить ошибку в стиле (int64=1) != (int=1)

2. Контроль количества вызовов

- gomock по умолчанию разрешает только один вызов метода
- mockery и minimock позволяют неограниченные вызовы
- Двойственная ситуация: gomock помогает поймать лишние вызовы, но требует явного Times() или AnyTimes()

3. Тестирование асинхронного кода

- mockery: приходится встраивать каналы через RunAndReturn — плохо масштабируется
- gomock: нужен самописный хелпер с controller.Satisfied()
- minimock: встроенная поддержка через mc.Wait(timeout)

————

Выбор автора, предсказуемо — minimock как "самый простой и топорный, покрывающий 99% случаев".

И я в целом согласен: строгая типизация экономит время на дебаге, встроенная поддержка асинхронности избавляет от костылей.

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

#article #testing #mocks
50👍12🤔2
Bubble Tea — TUI-фреймворк для Go

https://habr.com/ru/articles/939574/

Коротенький обзор фреймворка Bubble Tea. Сам обзор ни чем особо не примечателен, но фреймворк шикарный, очень рекомендую. Если вы любите красивые консольные утилиты. вам точно понравится.

#article #tui
👍11🔥8
Golang Дайджест
Bubble Tea — TUI-фреймворк для Go https://habr.com/ru/articles/939574/ Коротенький обзор фреймворка Bubble Tea. Сам обзор ни чем особо не примечателен, но фреймворк шикарный, очень рекомендую. Если вы любите красивые консольные утилиты. вам точно понравится.…
🦄 Экосистема Charm: полезные инструменты для терминала

Раз уж на то пошло, советую обратить внимание вообще на все проекты Charm, там много интересного. Например:

- Bubbles — готовые компоненты для Bubble Tea: текстовые поля, списки, таблицы, прогресс-бары, спиннеры.

- Lip Gloss — библиотека стилей для терминальных приложений. Цвета, рамки, отступы, выравнивание — всё как в CSS, только для консоли. Используется как база для Bubble Tea.

- Gum — эдакий мост между Bubbles / Lip Gloss и shell-скриптами. То есть, можно делать те же красивые скрипты, но без кода на Go.

- Glow — рендеринг Markdown прямо в терминале с подсветкой синтаксиса и красивым форматированием. Можно читать README не выходя из консоли.

- VHS — записывает GIF/видео демонстраций терминальных приложений через простой скрипт. Идеально для документации и README.

- Soft Serve — self-hosted Git-сервер с TUI интерфейсом. Можно красиво смотреть репозитории, коммиты и файлы прямо через SSH

Ну и наше любимое:
- Crushкрасивый консольный ИИ-агент . Поддерживает разные LLM (Claude, GPT, Gemini), использует LSP для контекста как в IDE, можно переключаться между моделями на лету.

Это только самое интересное, но там ещё много всякого. Советую пройтись по всему списку проектов и ознакомиться с каждым.

Вся экосистема построена вокруг идеи: терминал может быть красивым и удобным. И у них это отлично получается

Ну да, люблю я свистелки и перделки, теперь вы знаете обо мне всё 💅

Теперь подумываю сделать большое обзорное видео про всё это. Будет ли вам такое интересно?

#cli #tui
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍18🔥41
🐳 Container-aware GOMAXPROCS: Go наконец-то видит лимиты контейнеров

Пост в официальном блоге разработчиков Go, где они подробно рассказывают суть проблемы и как устроено недавнее техническое решение.

Go Team решили давнюю проблему совместимости с контейнерами. До версии 1.25 Go определял все ядра хоста, не учитывая CPU limits контейнера. Теперь GOMAXPROCS выставляется в соответствии с лимитами автоматически.

Суть проблемы:

- Контейнеру выделено 2 CPU на машине с 128 ядрами
- Go видит 128 ядер, создаёт кучу тредов
- Linux throttling тормозит приложение каждые 100ms
- Tail latency растёт

Что изменилось в 1.25:

- Go читает cgroup CPU limits и ставит GOMAXPROCS по ним
- Динамически обновляется при изменении лимитов
- Работает из коробки — просто обновите go.mod
- CPU requests игнорируются (только limits)

————

Наконец-то.. Проблеме много лет, и всё это время приходилось костылить через uber/automaxprocs или ENV-переменные. А теперь оно работает из коробки, как и должно было уже давно.

P.S. В Java эту проблему решили ещё в 2017 году 😩

#go1_25 #go_official #kubernetes #docker
Please open Telegram to view this post
VIEW IN TELEGRAM
20🔥18🤯2🤔1
Николай Тузов
🥂Выпуск про Go 1.25 уже доступен / GoGetPodcast 17 https://youtu.be/fHuJNsZPCJ0 Этого ролика вам точно будет достаточно для полного понимания нововведений, вне зависимости от вашего опыта Подробно обсудили, что нового в новой версии, зачем это нужно, как…
🥂Что нового в Go 1.25 — глубокий разбор изменений / GoGetPodcast

https://youtu.be/fHuJNsZPCJ0

Этого ролика вам точно будет достаточно для полного понимания нововведений, вне зависимости от вашего опыта

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

Дима был очень хорош, такого подробного и глубокого разбора вы больше нигде не увидите, а с комментариями Глеба оно ещё круче, очень рекомендую.

#gogetpodcast #podcast
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥19👍63
Forwarded from Go Update
🏗️ gogrep — инструмент для семантического поиска внутри вашей кодовой базы. 🏗️

Наверняка много кому приходилось сталкиваться с ситуацией «надо по коду найти вызовы по определенному паттерну». Чаще всего для этого мы используем регулярные выражения (grep, ag, rg). Однако у них всех есть один минус — они интерпретируют файлы как текст, а не как код. Из-за этого в результаты поиска попадают как нужные нам места вызова, так и комментарии, участки текста и прочая.

Решение этой проблемы: семантический поиск. Это когда утилита разбивает файл на синтаксическое дерево и производит поиск уже по самому дереву. Приведу простой пример:

~/mws/api > gogrep . 'ptr.Get($_)'


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

Документация по gogrep доступна тут. С описанием синтаксиса немного сложнее: большую (и лучшую) часть информации по мэтчингу и по фильтрам можно найти в тестах. Сама тулза является часть куда более мощной тулзы go-ruleguard (которая кстати входит в golangci-lint).

За обе утилиты огромнейшее спасибо Искандеру Шарипову.
🔥11👍1
Go Update
🚀 Расширение функции new для создания указателя на значения 🚀 Отличные новости! Предложение, обсуждение которого которого длится уже больше четырех лет и которое выдвинул сам Роб Пайк, наконец-то подходит к принятию. В чем суть: есть у нас встроенная функция…
Наконец-то можно будет выкинуть из проектов мой "любимый" lo.ToPtr()

Правда остаётся ещё lo.FromPtr(), но надежда уже есть.

Если что, мне жутко не нравится идея тащить в проект samber/lo, но не всегда удаётся с этим бороться. При этом, я даже не знаю что хуже — тащить этого монстра ради пары строк кода, или же желание использовать ещё больше его функционала 😩

К слову, в предыдущем выпуске подкаста тема `lo` очень подробно обсуждалась
в самом конце. Советую послушать, если нужны аргументы.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥32
Forwarded from Go Update
✔️ errors.AsType — типобезопастная замена errors.As ✔️

Тем временем, в 1.26 нас (вероятно) ждет еще одно приятное изменение: дженерики наконец доберутся до пакета errors.

Все изменение проще описать тремя строчками кода. В 1.25 у нас вот так:


var pe *fs.PathError
if errors.As(err, &pe) {
fmt.Println("Failed at path:", pe.Path)
}


А в 1.26 можно будет вот так:


if pe, ok := errors.AsType[*fs.PathError](err); ok {
fmt.Println("Failed at path:", pe.Path)
}


Вроде и небольшое изменение, но оно ведет, как минимум, к двум положительным вещам:
• Зона видимости типизированной ошибки во многих участках у нас теперь будет меньше, а значит меньше захламляется пространство имен и снижается необходимость думать над правильным именем для ошибки.
• В отличии от errors.As, который вторым аргументом принимал any, новая функция принимает только тех, кто реализует интерфейс error. Несмотря на то, что у нас есть проверка внутри go vet проверяющая второй аргумент у As, всегда приятнее когда компилятор может самостоятельно поймать ошибку на этапе сборки приложения.

Кстати, причина по которой сигнатура текущей функции выглядит как As(err error, target any) bool заключается в том, что указатель на интерфейс и указатель на тип реализующий интерфейс для компилятора две несовместимые конструкции. Иначе говоря, вот такой код


func As(err error, target *error) bool {
panic("unimplemented")
}



pe *fs.PathError
if As(err, &pathError) {
fmt.Println("Failed at path:", pathError.Path)
}





компиляцию не пройдет. А причина в том, что интерфейсы у нас это отдельная сущность которая существует не только во время компиляции, но и во время выполнения.
🔥263
Forwarded from go-with-me
⚡️ Concurrency Patterns. Fan In
В предыдущем посте мы немного напутали с определением такого многопоточного паттерна как Fan Out

На деле мы показывали Tee, который распространяет одно и то же значение V из канала-источника на N каналов-потребителей

Отличие Fan Out от Tee в том, что на N каналов распространяются разные значения из одного канала-источника. Тобишь, воркеры тянут значения из одного канала, борясь за них насмерть

Лирическое отступление закончено, наша совесть чиста, а сегодняшняя тема будет посвящена Fan In

Этот паттерн является обратным для Fan-Out. Мы собираем данные из нескольких каналов-источников и направляем их в один общий канал-потребитель


1. Default
Итак, что мы имеем?
— Есть воркеры — они кладут значения в N каналов и являются продьюсерами
— Каждый из этих N каналов будет получать значения от своего продьюсера. Назовем такие каналы "стоковыми"
— Есть один общий канал out, туда будет нужно отправить все значения из стоковых каналов
— Для этого мы запускаем N потоков, каждый из которых слушает свой стоковый канал, куда кладет значения продьюсер и редиректит все значения в out

Playground пример

Но что же будет, если какой-то наш продьюсер потух и больше не шлет никаких значений, а передаггый контекст не отменен? Как бы нам понять, что воркер не является активным и перезапустить его? — в этом нам поможет такой механизм как "Heartbeats"

Heartbeat — это регулярное сообщение от продьюсера/воркера, подтверждающее, что он жив и работает


2. Heartbeats
Приступим к рассмотрению этого чуда!

Основная идея проста:
— Имеем структуру, которая хранит в себе стоковый канал, используемый как пайп между воркером и стоком, и канал "сердцебиений"
— Функция Supervise ответственна за отслеживание "сердцебиений" и перезапуск воркера при их отсутствии по TTL
— Функция FanIn принимает на вход стоковые каналы и возвращает результирующий канал, из которого можно читать данные

Всмотримся в наши функции поподробнее

2.1. FanIn
— Не отклоняемся от цели: выкачиваем данные из стоковых каналов и перекладываем в out, реагируя на контекст и неблокирующе отправляя "сердцебиение" нашему супервизору, который пристально наблюдает за нашими воркерами
WaitGroup здесь так же используется для того, чтобы дождаться конца работы наших стоков и отдать управление основному потоку
после дренажа всех "живых" значений

2.2 Supervise
— Создаем стоковый канал и канал "сердцебиений", агрегируем эти значения в структуре Source и возвращаем ее
— В отдельном потоке запускаем нашу рутину по отслеживанию и перезапуску воркеров

2.2.1 Смотрим на внутренности запущенного потока внутри Supervise
— Изначально происходит создание дочернего контекста с отменой для нашего воркера. Этот контекст будет рулить в тот момент, когда наш TTL пройдет и надо будет потушить воркера
— Создаем ticker, который будет слать ивенты, семантически значащие следующее: "в нашего воркера стреляли и он упал в лужу на..."
После получения ивента мы отменяем контекст и воркер окончательно "задыхается в луже"
— Первично запускаем работягу в отдельном потоке
— Если ловим ивент от тикера: производим отмену контекста, переназначаем этот же контекст и функцию отмены, сбрасываем таймер, и запускаем нового воркера в отдельном потоке
— В случае, когда из стокового потока нам пришло "сердцебиение" мы просто сбрасываем таймер и движемся дальше!

Стоит отметить, что воркеры должны "реагировать" на переданный контекст. Без этого мы получим утечку потоков и черт его знает, чем нам это грозит (профилированием и
устранением проблемы, которой можно было бы и избежать)

Таким образом, мы получаем более надежный Fan In, где все источники данных контролируемы и восстанавливаемы при зависаниях

Playground пример


Статью писали с Дашей: @dariasroom

Stay tuned 😏
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍96🔥2🤯1
conc — удобные примитивы для конкурентного кода

https://github.com/sourcegraph/conc

⭐️ ~10.1k

Небольшая библиотека от Sourcegraph, которая предлагает более безопасные и удобные обёртки над стандартными инструментами конкурентности в Go.

Впервые встретил её на своей текущей работе, и в целом мне понравилось, поэтому грех не поделиться.

Что в ней есть интересного:

- conc.WaitGroup — альтернатива стандартному sync.WaitGroup: ловит паники в горутинах и возвращает их в Wait(), а также не даёт забыть вызвать Wait()

- pool — конкурентный пул задач с ограничением числа горутин (WithMaxGoroutines), сбором ошибок (WithErrors, WithFirstError) и отменой задач при ошибках (WithContext)

- stream — параллельное выполнение задач с сохранением порядка результатов (удобно, когда порядок важен, но хочется параллелизма)

- iter.Map / ForEach — упрощённые хелперы для конкурентной обработки слайсов

🟠 Библиотека пока pre-1.0 (последний релиз в феврале 2023), API может меняться.

#library #concurrency #goroutines
Please open Telegram to view this post
VIEW IN TELEGRAM
12👍10🤯1
📆Go-разработка в 2025 году — как оценить ситуацию на рынке и в индустрии?

Как меняется стек, какие практики и инструменты становятся стандартом, как работают команды и какие задачи сейчас на передовой?

Ответить на эти и многие другие вопросы можно только одним способом — провести исследование: опросить как можно больше специалистов, обработать данные и показать результаты в удобном формате.

Именно этим уже несколько лет подряд занимается команда DevCrowd. И они снова запускают ежегодное исследование русскоязычных Go-разработчиков.

🟢От себя честно скажу: ребята делают очень классную и важную работу для нашего сообщества.
Посмотрите
прошлое исследование — там очень много интересных и полезных данных, но читается всё это очень легко, благодаря шикарной подаче.
Поэтому я считаю, что проект обязательно нужно поддержать.


Присоединяйтесь — помогите собрать честный и актуальный срез профессии.
Не забудьте там упомянуть и мой канал, если он вам нравится, для меня это очень важно ❤️

Зачем участвовать?

– Сравните свои задачи, подходы и процессы с коллегами
– Узнаете, какие технологии и практики в ходу у коллег
– Получите ориентиры для развития и найма
– Сделаете профессию Go-разработчика прозрачнее для сообщества и рынка

📊 Результаты исследования будут в начале ноября на devcrowd.ru
Заполнение не долгое, займёт ~10 минут

🫶 Пройти опрос

👴 Результаты прошлого года

#devcrowd #research
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5👍32🤯1