Библиотека Go-разработчика | Golang
24K subscribers
2.57K photos
48 videos
88 files
5.1K links
Все самое полезное для Go-разработчика в одном канале.

По рекламе: @proglib_adv

Учиться у нас: https://proglib.io/w/32d20779

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0

#WXSSA
Download Telegram
🤔 Спам тимлидам, фейковые офферы и приукрашенное резюме

IT-рынок 2026 года — это не конкурс честных и талантливых. Компании говорят об экологичной культуре, а сами гостят после четырёх этапов отбора.

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

➡️ Узнать приёмы тех, кто смог

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
This media is not supported in your browser
VIEW IN TELEGRAM
😁6
👍 На курсе по контролируемой разработке AI-агентов мы будем разбирать ровно то, о чём говорит Владислав в голосовом, но уже в формате системной практики.

📅 Старт курса — 20 апреля.

Если хотите разобраться, как строить управляемые агентные системы:
➡️ Присоединяйтесь.

P.S. С первого занятия будет практика: код и разбор реальных ошибок, а не только теория.
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱5👍1
🔄 Go 1.26.1 и 1.25.8

Вышли новые версии Go. Ничего революционного, просто патчи безопасности.

В crypto/x509 нашли проблему с проверкой email-адресов в сертификатах. Когда сертификат содержит несколько ограничений на emai система игнорирует все ограничения кроме последнего.

В html/template нашли проблему с экранированием URLs в meta-тегах. Если у вас в контенте есть refresh meta-тег и вы туда подставляете какой-то URL через действия шаблона, он не будет экранирован.

net/url.Parse оказывается принимал невалидные IPv6-адреса, потому что недостаточно проверял хост-компонент. Теперь IPv6-литералы должны стоять в начале хоста, остальное будет отклонено.

➡️ Анонс

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍86🔥1😁1
👨‍💻 Горутины живут своей жизнью: как не создать утечку памяти

Горутины дешёвые, но не бесплатные. Каждая занимает минимум 2KB памяти. Когда запускаете сотни или тысячи горутин, это становится ощутимо. Но главная проблема не в памяти, а в том, что горутина может зависнуть и никогда не завершиться.

Проблема с time.Sleep

Часто видим такой паттерн:
func Job(d time.Duration) {
for {
doWork()
time.Sleep(d)
}
}


На первый взгляд это удобно. Но когда приложение получает SIGTERM и нужно выключиться, горутина может быть посередине sleep. Она просто проигнорирует сигнал выключения и продолжит спать. Graceful shutdown не будет таким graceful.

time.Sleep не знает про контекст и не может быть прерван. Поэтому используйте context:
func Job(ctx context.Context, d time.Duration) {
for {
select {
case <-ctx.Done():
return
default:
doWork()
time.Sleep(d)
}
}
}


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

Утечки через каналы

Вот другой сценарий:
func worker(jobs <-chan int) {
for i := range jobs {
process(i)
}
}

jobs := make(chan int)
go worker(jobs)


Выглядит просто. Закроем канал jobs и горутина выйдет. Но что если где-то в коде забыли закрыть канал? Горутина будет ждать бесконечно. Даже не упадёт, просто повиснет в памяти. Утечка.

Часто это происходит, когда забывают про defer или неправильно структурируют код. Горутина ждёт данных из канала, но никто их туда не отправляет.

Как правильно

Главное правило: сделайте очевидным, когда горутина стартует и когда заканчивается. Не надо полагаться на магию вроде автоматического закрытия канала.

Передавайте context во все горутины, которые крутятся долго. Используйте select с <-ctx.Done(). Явно закрывайте каналы, по которым читаете. Не создавайте горутины просто так, всегда планируйте как их остановить.

Если горутина может зависнуть, добавьте таймаут:
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()

go worker(ctx, jobs)


Каждая горутина которую вы запускаете, это потенциальная утечка если забыть её корректно завершить. Всегда знайте, как горутина заканчивается. Context, каналы и таймауты это ваши друзья.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1611
Что выведет код

В коде есть функция вывода, но успеет ли она отработать до выхода из прогарммы?

➡️ Ответ смотрите по ссылке

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔4🔥3😁1
💿 Ещё одна ORM для Go

Берешь популярную ORM, она обещает удобство, а потом выясняется, что код либо медленный, либо писать его больнее, чем на сыром SQL. Ent от Meta подходит к проблеме иначе.

Вместо того чтобы выбирать между скоростью и удобством, Ent просто генерирует тебе type-safe код прямо из схемы. Пишем структуру в Go, и она автоматически становится слоем работы с БД.

Полезные фичи

Поддержка PostgreSQL JSONB из коробки. Если нужны гибкие структуры данных, не нужно городить велосипед с отдельной таблицей или JSON-полем, которое трудно индексировать.

Миграции генерируются автоматически. Меняете схему, и CLI сам создает SQL. Конечно, проверить стоит, но руки уже не болят от написания однотипного кода.

GraphQL встроен в архитектуру. Ваша модель данных тут же становится запрашиваемой. Не нужно отдельно писать резолверы для каждого поля.

Вот как выглядит код на практике:
client.User.
Create().
SetName("Aashish").
SetEmail("aashish@example.com").
Save(ctx)


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

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍147🥱2
💥 Открытый вебинар | ИИ-агенты в продакшене: от хайпа к деньгам

Агенты уже везде. Но мало кто признаётся, сколько денег сжёг на бесконечных циклах, галлюцинациях в RAG и отсутствии мониторинга.

Полина Полунина, руководитель AI-направления Альфа-Банка, расскажет честно:

▪️ Чем агент отличается от «просто GPT с промптом» и когда бизнесу достаточно обычного LLM
▪️ 3 реальных кейса из корпоративной среды: что взлетело, а что нет
▪️ Live-демо работающего агента
▪️ ТОП-5 граблей, на которые наступают команды при внедрении

⏱️ 10 марта в 19:00 (МСК)

🎁 Участники получат промокод на скидку на самый полный курс по ИИ-агентам

👉 Регистрируйся
💃 Дайджест недели

Пришло время собрать интересные материалы первой недели весны.

Go 1.26.1 и 1.25.8

Вам не нужна Kafka

mus-go обновился

За простоту не повышают

Спам тимлидам, фейковые офферы и приукрашенное резюме

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
1
⚠️ time.After vs time.NewTimer: почему первый опасен

Частый вопрос на собеседованиях. Многие думают, что time.After безобиден, но это не совсем так.

Проблема в том, что time.After создает таймер, который остается в памяти до истечения времени. Если вызывать это в цикле часто, каналы накапливаются:
for {
select {
case event := <-ch:
handle(event)
case <-time.After(15 * time.Minute):
fmt.Println("timeout")
}
}


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

Решение простое — используйте time.NewTimer и явно останавливайте:
timer := time.NewTimer(15 * time.Minute)
select {
case event := <-ch:
handle(event)
if !timer.Stop() {
<-timer.C
}
case <-timer.C:
fmt.Println("timeout")
}


Теперь таймер останавливается после события, и память освобождается.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍212😢2
🧑‍💻 DI контейнер для Go, когда Wire не хватает

Flora это инструмент генерации dependency injection контейнера для Go. Вот что он делает и есть ли в этом смысл.

В Go два основных подхода к DI:

1. Google Wire
Вы вручную пишете провайдеры и собираете граф зависимостей. Работает, но это бойлерплейт. Каждый сервис требует явной проводки.

2. Рефлексия
Фреймворки типа Spring используют рефлексии. Медленнее, ошибки в рантайме, но меньше кода.

Flora предлагает третий путь: автогенерация на основе маркеров в коде.

Как это работает

Вы маркируете структуру с flora.Component:
type UserService struct {
flora.Component
}

func NewUserService() *UserService {
return &UserService{}
}


Запускаете flora gen и он генерирует Wire-код автоматически. Как минимум сокращает бойлерплейт.

Это компромисс между статичностью Wire и удобством фреймворков. Работает, генерирует валидный Go код, но нужно время чтобы понять нужен ли вам еще один инструмент в проекте.

➡️ Репозиторий

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8👍32🌚2
🤩 Контракты, которые говорят правду

Большие интерфейсы скрывают, что на самом деле нужно функции. Вместо этого определите ровно то, что используете.

Когда передаёте целую структуру с десятком методов, непонятно, какой из них вообще нужен:
func GenerateReport(db *Database) (Report, error) {
// Использует только db.Query(), остальное не нужно
}


Кто это читает, должен лезть в реализацию и разбираться. Тестировать сложно — нужно создавать весь Database.

Решение

Объявляйте интерфейс в точке использования, только с нужными методами:
type ReportQuerier interface {
Query(query string) ([]Row, error)
}

func GenerateReport(q ReportQuerier) (Report, error) {
rows, err := q.Query("SELECT * FROM sales")
if err != nil {
return Report{}, fmt.Errorf("query sales: %w", err)
}
return Report{Data: rows}, nil
}

// Тестировать элементарно
type mockQuerier struct {
rows []Row
}

func (m mockQuerier) Query(string) ([]Row, error) {
return m.rows, nil
}


Интерфейс это контракт. Глядя на сигнатуру, сразу видно: функция только читает данные, ничего не меняет.

Реальный пример

Вместо передачи всего HTTP клиента или случайного объекта, определяйте узкие интерфейсы:
type MetricsReporter interface {
Report(metric string, value float64) error
}

func ProcessData(data []Data, reporter MetricsReporter) error {
for _, d := range data {
if err := reporter.Report("items_processed", 1); err != nil {
return fmt.Errorf("report metrics: %w", err)
}
}
return nil
}


Когда комбинируете мини-интерфейсы с options паттерном, код становится понятным сам по себе:
type OrderProcessor struct {
repo OrderRepository
payment PaymentGateway
metrics MetricsReporter
}

type OrderRepository interface {
Get(id string) (Order, error)
Save(order Order) error
}

type PaymentGateway interface {
Charge(id string, amount float64) error
}

type MetricsReporter interface {
Increment(metric string) error
}

// Options паттерн для конфигурации
type ProcessorOption func(*OrderProcessor)

func WithMetrics(m MetricsReporter) ProcessorOption {
return func(p *OrderProcessor) {
p.metrics = m
}
}

func NewOrderProcessor(
repo OrderRepository,
payment PaymentGateway,
opts ...ProcessorOption,
) *OrderProcessor {
p := &OrderProcessor{
repo: repo,
payment: payment,
metrics: &noopMetrics{},
}
for _, opt := range opts {
opt(p)
}
return p
}

func (p *OrderProcessor) Process(id string) error {
order, err := p.repo.Get(id)
if err != nil {
return fmt.Errorf("get order: %w", err)
}

if err := p.payment.Charge(id, order.Total); err != nil {
return fmt.Errorf("charge: %w", err)
}

if err := p.repo.Save(order); err != nil {
return fmt.Errorf("save order: %w", err)
}

p.metrics.Increment("orders_processed")
return nil
}


Глядя на эту функцию, вы сразу знаете, что нужно:

• Какие зависимости нужны: интерфейсы явно показаны
• Как настроить
• Что делается: названия методов
• Что может пойти не так: обёртывание ошибок с контекстом

Мини-интерфейсы это не просто стиль. Это способ заставить код быть честным с тем, кто его читает.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍12🔥42🌚1
🤝 По резюме не берут. Берут по рекомендации

70–80% IT-вакансий закрываются ещё до того, как попадают на джоб-борды. Не потому что компании скрывают позиции — просто у кого-то из команды уже есть нужный человек на примете.

Реферальный найм в 2026 году — это не лайфхак, а отдельный рынок труда. И если вы о нём не знаете, вы конкурируете только за публичные вакансии.

➡️ Как устроиться по рекомендации и где искать реферальные программы

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
☝️ Уже сегодня: ИИ-агенты в продакшене — инженерный подход к интеграции LLM

Индустрия активно обсуждает потенциал нейросетей, способных автоматизировать бизнес-процессы и заменить целые отделы. Однако реальное внедрение агентов в production вскрывает серьёзные проблемы: разработчикам приходится бороться с непредсказуемыми галлюцинациями моделей, нестабильными API и сложной интеграцией в существующую архитектуру.

Сегодня в 19:00 МСК в рамках нашего курса «Разработка AI-агентов» мы проведём открытый вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке. Будем говорить о нейросетях с позиции жёсткой инженерии.

Разберём три реальных кейса из сурового банковского энтерпрайза, напишем и запустим агента прямо в эфире, честно обсудим грабли, на которые наступает бизнес при интеграции LLM.

Тем, кто придёт на эфир, дадим промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
Часовая готовность: создаём ИИ-агента в прямом эфире

В 19:00 МСК в рамках нашего курса «Разработка AI-агентов» стартует вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке.

Будет live-демо работающего агента, реальные метрики из корпоративной среды и честный разбор архитектурных граблей — без воды и «успешного успеха».

Всем зрителям эфира дадим эксклюзивный промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
1👍1
🛠 Конкурентность не делает код быстрее автоматически

Многие разработчики, столкнувшись с задачей ускорить код, сразу думают о конкурентности. Горутины дешевле потоков, каналы выглядят элегантно, паттерны Fan-Out/Fan-In хорошо описаны в документации. Всё это создаёт иллюзию, что конкурентность и производительность — это одно и то же.

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

Бенчмарк:
package benchmark

import (
"sync"
"testing"
)

// Сама задача: умножить на 20, затем возвести в квадрат
func process(n int) int {
n = n * 20
return n * n
}

// Последовательный подход
func sequential(numbers []int) []int {
result := make([]int, len(numbers))
for i, n := range numbers {
result[i] = process(n)
}
return result
}

// Конкурентный подход через Fan-Out / Fan-In
func concurrent(numbers []int) []int {
numWorkers := 4

jobs := make(chan int, len(numbers))
results := make(chan int, len(numbers))

var wg sync.WaitGroup
for w := 0; w < numWorkers; w++ {
wg.Add(1)
go func() {
defer wg.Done()
for n := range jobs {
results <- process(n)
}
}()
}

for _, n := range numbers {
jobs <- n
}
close(jobs)

go func() {
wg.Wait()
close(results)
}()

out := make([]int, 0, len(numbers))
for r := range results {
out = append(out, r)
}
return out
}

// Генерация тестовых данных
func makeNumbers(n int) []int {
nums := make([]int, n)
for i := range nums {
nums[i] = i + 1
}
return nums
}

// Бенчмарки

func BenchmarkSequential_100(b *testing.B) {
nums := makeNumbers(100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sequential(nums)
}
}

func BenchmarkConcurrent_100(b *testing.B) {
nums := makeNumbers(100)
b.ResetTimer()
for i := 0; i < b.N; i++ {
concurrent(nums)
}
}

func BenchmarkSequential_10000(b *testing.B) {
nums := makeNumbers(10000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
sequential(nums)
}
}

func BenchmarkConcurrent_10000(b *testing.B) {
nums := makeNumbers(10000)
b.ResetTimer()
for i := 0; i < b.N; i++ {
concurrent(nums)
}
}


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

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

Конкурентность даёт выигрыш тогда, когда горутины большую часть времени ждут чего-то внешнего: ответа от базы данных, ответа от API, чтения с диска. Пока одна горутина ждёт, другие работают. Вот здесь конкурентность оправдана.

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍10🥱82😁2
👨‍👩‍👧‍👦 Топ-вакансий для Go-разработчиков за неделю

Backend Engineer — от 175 000 до 325 000 ₽, удаленно.

Middle Go разработчик — от 224 700 ₽, удаленно.

Team Lead Go — от 450 000 до 600 000 ₽, удаленно в Москве.

➡️ Еще больше топовых вакансий — в нашем канале Go jobs

🐸 Библиотека Go-разработчика

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
👍21
👨‍💻 Стандартный flag, Cobra или urfave/cli

Каждый раз, когда Go-разработчик начинает новый CLI-инструмент, возникает один и тот же вопрос: какую либу брать? Cobra, urfave/cli, стандартный flag или вообще Bubbletea?

Cobra — выбор по умолчанию для большинства. Используется в kubectl, Hugo, GitHub CLI. Поддерживает вложенные команды, автогенерацию хелпа, наследование флагов. Хорошо работает в связке с Viper для конфигов.

Но есть нюанс: Cobra берёт контроль над структурой приложения. Если тебе нужен простой тул на 200 строк, она может ощущаться как фреймворк ради фреймворка.

urfave/cli проще и прямолинейнее. Нет инверсии контроля, API читается легче. Хороший выбор, когда команд немного и не нужна глубокая иерархия. Минус — экосистема поменьше, и при росте проекта можно упереться в ограничения.

Стандартный flag вообще не либа, а пакет из коробки. Если CLI простой и флагов штук пять, иногда правда не надо тащить зависимости.

Bubbletea стоит отдельно — это TUI-фреймворк, а не парсер аргументов. Cobra и Bubbletea часто используют вместе: первая разбирает команды, вторая рисует интерфейс в терминале.

💬 Что будете брать под CLI-тулзу? Ответы в комменты 👇

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
7
👨‍💻 PVS-Studio запускает бета-тест анализатора для Go

PVS-Studio известна своим статическим анализатором для C, C++ и C#. Теперь команда добралась до Go.

С 6 апреля начинается бета-тестирование. Первая версия включает около двух десятков диагностических правил, CLI-утилиту и плагин для GoLand. Поддержка VS Code запланирована позже.

Чтобы попасть в программу, нужно заполнить форму на сайте pvs-studio.com и указать email. 6 апреля придёт письмо с инструкциями. Если найдёте ошибки, ложные срабатывания или крэши, команда просит сообщать через форму обратной связи.

➡️ Источник

📍 Навигация: ВакансииЗадачиСобесы

🐸 Библиотека Go-разработчика

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2