Библиотека Go-разработчика | Golang
23.3K subscribers
2.17K photos
43 videos
87 files
4.55K links
Все самое полезное для Go-разработчика в одном канале.

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

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

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

РКН: https://gosuslugi.ru/snet/67a4a8c2468
Download Telegram
🥤 Как писать универсальный код в Go

Дженерики в Go позволяют писать один алгоритм для разных типов без копипасты и без interface{}. Это про выразительность и про безопасность типов — меньше дублирования, больше проверок на этапе компиляции.

Пример сравнения разных типов одним методом:
func Compare[T ~int | ~int64 | ~float64 | ~string](a, b T) int {
if a < b {
return -1
} else if a > b {
return 1
}
return 0
}


Типобезопасная коллекция без приведения типов:
type Set[T comparable] map[T]struct{}

func NewSet[T comparable]() Set[T] { return make(Set[T]) }

func (s Set[T]) Add(v T) { s[v] = struct{}{} }
func (s Set[T]) Has(v T) bool { _, ok := s[v]; return ok }
func (s Set[T]) Delete(v T) { delete(s, v) }

func main() {
users := NewSet[string]()
users.Add("alice")
users.Add("bob")

nums := NewSet[int]()
nums.Add(1)
nums.Add(2)

fmt.Println(users.Has("bob")) // true
fmt.Println(nums.Has(3)) // false
}


Практические советы

• Если функция нужна в одном месте — дженерик может быть избыточен.
• Дженерики — про DX и безопасность типов; ускорение зависит от конкретного кода.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
6🥱4👍2
🆕 Дайджест недели

Сегодня последний день недели и это значит, что пришло время для сборника материалов.

Время высказаться

Команда Go открыла ежегодный опрос разработчиков — Go Developer Survey 2025. Пройти его можно до 30 сентября.

Outbox-паттерн в Go + Postgres

Вместо того чтобы сразу пушить событие в брокер, сервис пишет его в таблицу outbox в той же транзакции, что и бизнес-изменение. Дальше отдельный воркер периодически читает «необработанные» записи, публикует их и помечает как processed. Так достигается at-least-once доставка, а потребители обязаны быть идемпотентными.

Новый Cup o' Go

В свежем выпуске подкаста Cup o’ Go — обзор новостей: экспериментальный JSON API для Go, опрос разработчиков 2025 года, статья о том, почему стоит тестировать состояние, а не взаимодействия, и даже история о том, как линтер «сломал» код.

Go Task v3.45.3

Оптимистическая vs пессимистическая блокировка

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
➡️ Выбираем направление на неделю

Контент недели — в ваших руках.
Мы соберем материалы, практики и гайды именно по выбранному направлению.

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
🕵️ Обнаружение утечек горутин

Утечки горутин не всегда заметны — сервис вроде работает, но число горутин медленно растёт.

Проверить можно прямо в тесте:
func TestHandler_TestLeaks(t *testing.T) {
initial := runtime.NumGoroutine()
err := testHandler()
require.NoError(t, err)
time.Sleep(100 * time.Millisecond) // время на очистку
final := runtime.NumGoroutine()
assert.InDelta(t, initial, final, 2, "Есть утечка")
}


Также используйте pprof/trace для проверки количества горутин в /debug/pprof/goroutine и трассировки их жизненного цикла

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
🎧 Топ вакансии недели

Go-разработчик
с удалёнкой в Москве и ЗП до 400 тысяч ₽.

Гибрид для Go-разработчика с вилкой 250-400 тысяч ₽.

Мидл эникей на Go с гибридом в Москве.

Вакансия для тех, кто хочет стать частью команды ProgLib — Бустер

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

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Не пропустите событие осени для AI-комьюнити

24 сентября, 19:00 Мск — бесплатный вебинар с Максимом Шаланкиным «ИИ-агенты: новая фаза развития искусственного интеллекта»

😤 Пока все спорят, «боты это или нет», мы покажем, как работают настоящие агенты: с планированием, инструментами и памятью. За час Максим разберёт:
— почему ИИ-агенты сейчас на пике инвестиций
— чем они отличаются от ChatGPT и обычных моделей
— цикл агента: восприятие → планирование → действие → обучение
— живое демо простого агента
— как бизнес уже получает ROI до 80%

⚡️ Хотите спросить у Максима всё, что обычно остаётся «за кадром»? Ловите шанс — только в прямом эфире.

Мест мало, регистрация закроется, как только забьём комнату
😁21🤔1
🛠 Как работает JWT

JWT (JSON Web Token) — это компактный способ передачи информации между участниками через JSON-объект, защищённый подписью.

Что происходит по шагам:

• Аутентификация — пользователь вводит логин/пароль, сервер проверяет их и создаёт токен.

• Формирование токена из заголовка, пейлода и подписи. Всё это кодируется в Base64.

• Использование — клиент хранит токен (обычно в localStorage или cookie) и отправляет его в заголовке Authorization: Bearer <token> при каждом запросе.

• Проверка — сервер расшифровывает токен, сверяет подпись и срок действия. Если всё совпадает, запрос считается доверенным.

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

#GoVisual
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🥱3
🏭 Фабрика: когда конструктор — это функция

В классическом ООП фабрика — это отдельный объект, который возвращает разные реализации интерфейса.
В Go всё проще: фабрика = обычная функция, которая возвращает интерфейс или конкретный тип.

Представьте, у нас есть сервис оплаты. Способов много: карта, СБП, крипта. Хотим переключаться динамически, но при этом не тянуть жёсткие зависимости в код.

Пример:
package main

import "fmt"

// общий контракт
type Payment interface {
Pay(amount float64) string
}

// конкретные реализации
type Card struct{}
func (c Card) Pay(amount float64) string {
return fmt.Sprintf("💳 Оплата картой: %.2f₽", amount)
}

type SBP struct{}
func (s SBP) Pay(amount float64) string {
return fmt.Sprintf("📲 Перевод через СБП: %.2f₽", amount)
}

type Crypto struct{}
func (c Crypto) Pay(amount float64) string {
return fmt.Sprintf("₿ Криптой: %.2f₽", amount)
}


И сама фабрика:
// фабрика по выбору метода
func PaymentFactory(method string) Payment {
switch method {
case "card":
return Card{}
case "sbp":
return SBP{}
case "crypto":
return Crypto{}
default:
return nil
}
}


Использование:
func main() {
pay := PaymentFactory("sbp")
fmt.Println(pay.Pay(1599.50))
}


В стандартной библиотеке это повсеместно: http.NewRequest(), json.NewEncoder().

Такой подход отлично дружит с тестированием и моками. Хотите заменить оплату через карту на СБП или крипту? Просто подставьте другой конструктор.

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35🔥1👾1
✏️ Задача дня: 3Sum

Дан массив целых чисел nums. Требуется найти все уникальные тройки (a, b, c), такие что a + b + c = 0. Порядок элементов в тройке не важен, дубликаты недопустимы.

Идея оптимального решения

1. Сортируем массив (O(n log n)), чтобы упростить поиск и контроль дубликатов.

2. Фиксируем первый элемент i, затем две указки l и r («два указателя») пробегают подмассив справа/слева:

Если сумма < 0 → сдвигаем l++,

Если сумма > 0 → сдвигаем r--,

Если сумма == 0 → сохраняем тройку и пропускаем дубликаты вокруг l и r.

3. Пропускаем дубликаты и для i, чтобы не повторять стартовую точку.

Сложность: O(n^2) по времени и O(1) доп. памяти не считая результата.

Реализация:
package main

import (
"fmt"
"sort"
)

func threeSum(nums []int) [][]int {
sort.Ints(nums)
n := len(nums)
res := make([][]int, 0)

for i := 0; i < n; i++ {
// Пропускаем одинаковые стартовые значения
if i > 0 && nums[i] == nums[i-1] {
continue
}
// Ранний выход: дальше только положительные
if nums[i] > 0 {
break
}

l, r := i+1, n-1
for l < r {
sum := nums[i] + nums[l] + nums[r]
switch {
case sum < 0:
l++
case sum > 0:
r--
default:
res = append(res, []int{nums[i], nums[l], nums[r]})
// Пропускаем дубликаты для l
lVal := nums[l]
for l < r && nums[l] == lVal {
l++
}
// Пропускаем дубликаты для r
rVal := nums[r]
for l < r && nums[r] == rVal {
r--
}
}
}
}
return res
}

func main() {
examples := [][]int{
{-1, 0, 1, 2, -1, -4},
{0, 0, 0, 0},
{-2, 0, 1, 1, 2},
}

for _, nums := range examples {
fmt.Println("Input:", nums)
fmt.Println("Triplets:", threeSum(append([]int{}, nums...)))
}
}


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

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍136
Сегодня премьера

В 19:00 МСК стартует бесплатный вебинар с Максимом Шаланкиным«ИИ-агенты: новая фаза развития искусственного интеллекта».

В программе:
— почему агенты ≠ чат-боты;
— живое демо простого агента;
— и как эта тема встроена в курс, который разработан под руководством Никиты Зелинского.

Это прямой эфир: подключиться можно через лендинг курса.
🙏 Уволили за то, что нашёл уязвимость

Недавно на реддите один разработчик поделился историей: его уволили за то, что он нашёл уязвимость в системе компании и сообщил о ней бэкенд-разработчику.

Казалось бы — инициативность, забота о безопасности, защита бизнеса. Но результат оказался противоположным: увольнение. Автор поста теперь задаётся вопросом, можно ли что-то предпринять юридически и вообще правильно ли он поступил.

Ситуация неоднозначная. С одной стороны, ответственность за безопасность — это зона компании, и сотруднику логично сигнализировать о проблемах. С другой — всё упирается в корпоративную культуру: где-то за такие находки благодарят, а где-то воспринимают как «влез не в своё дело».

💬 Как вы думаете кто в этой ситуации неправ?

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
🌚5👾21
👨‍💻 Команды терминала, которые должен знать каждый разработчик

Многие знакомы с cd, ls, pwd, но под капотом терминала — море полезных шорткатов и трюков. Вот список тех, которые экономят время, исправляют ошибки и упрощают работу:

1. Запуск предыдущей команды — !!

Бывает забываешь написать sudo, тогда можно просто sudo !!

2. Заменить очепятку и выполнить команду заново — ^old^new

3. Заменить все вхождения в команде — !!:gs/old/new/

4. Поиск по тексту в файлах — grep -R "pattern" .

5. Открыть последнюю команду в редакторе для редактирования — fc

6. Проверка доступности порта — nc -zv <host> <port>

7. Проверить чем занят порт — lsof -i :<port>

Практикуйте — и они войдут в привычку.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍292😁2
🧑‍💻 Failsafe-go v0.8.4: проект снова в деле

Библиотека failsafe-go долго не обновлялась с прошлого года, и вот — свежий релиз. Разработчик вернулся к активной доработке инструмента для отказоустойчивости в Go.

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

v0.8.0 — серьёзная переработка API: политики стали более гибкими, добавились удобные билдеры и улучшена работа с асинхронностью.

v0.8.1–0.8.3 — фиксы и улучшения, связанные с управлением retry/timeout, плюс доработка логики fallback.

v0.8.4 — свежий релиз, в котором можно напрямую задавать Budget в retry и hedge-политиках

➡️ Репозиторий либы

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
1
👨‍💻 Маленький трюк, который срезал 35% задержки

Иногда для ускорения не нужны сложные оптимизации — достаточно пары строк кода. В одном проекте команда заметила, что при каждом JSON-энкодинге создаётся новый bytes.Buffer. Это вело к лишним аллокациям и работе GC.

Решение оказалось простым: вынести буфер в sync.Pool и переиспользовать его для json.NewEncoder. В итоге:

— меньше аллокаций
— меньше работы сборщика мусора
— задержка p99 снизилась примерно на 35%.

Вот как это сделать:
var bufPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}

func encodeJSON(w http.ResponseWriter, v interface{}) error {
buf := bufPool.Get().(*bytes.Buffer)
buf.Reset()
defer bufPool.Put(buf)

if err := json.NewEncoder(buf).Encode(v); err != nil {
return err
}

_, err := w.Write(buf.Bytes())
return err
}


Буфер не создаётся каждый раз заново — он берётся из пула и после использования возвращается обратно.

➡️ Источник

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍236👏1😁1
👨‍💻 Релиз инструмента для порт-форвардинга

Проект tunn — это небольшой инструмент для прокидывания портов. Его задача проста: быстро и прозрачно соединять локальные сервисы с внешними клиентами без лишних зависимостей.

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

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

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

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍43
🤫 Курс «ИИ-агенты для DS-специалистов»

Каждый технологический скачок оставляет позади тех, кто «подождал ещё чуть-чуть». ИИ-агенты — это новый рывок.

Уже через пару лет именно они будут драйвить аналитику и автоматизацию. Хотите остаться на гребне?

🖥️ На курсе «ИИ-агенты для DS-специалистов» мы разберём:

— создание AI-агентов с нуля
— сборку собственной RAG-системы
— интеграцию LLM под задачи бизнеса

📌 Курс подходит:

→ ML/AI инженерам (middle+ / senior)
→ Data Scientists
→ Backend и platform-инженерам
→ Advanced CS/DS студентам

⚡️ Старт уже скоро — 3 октября.

💰 До 28 сентября действует скидка — 57.000 ₽ вместо 69.000 ₽ (по промокоду datarascals).

🔗 Узнать больше о курсе и записаться

З.ы. если вы не успели на вебинар «ИИ-агенты: новая фаза развития искусственного интеллекта» — запись уже доступна
🥱51
🕵️‍♂️ 5 приёмов поиска утечек горутин в Go

Утечки горутин — скрытая проблема, которая со временем приводит к росту потребления памяти, деградации производительности и неожиданным падениям. В отличие от «обычных» багов, такие ошибки долго не проявляют себя, а в продакшене отлавливать их уже поздно.

Ниже 5 рабочих приёмов, которые помогут держать горутины под контролем.

1. Мониторинг количества горутин

Запуск фоновой задачи, которая периодически считывает runtime.NumGoroutine() и сравнивает с базовым уровнем — если количество горутин выросло выше порога, сигнализировать (лог, алерт).

go func() {
for range ticker.C {
n := runtime.NumGoroutine()
if n > base+50 { // ваш порог
log.Printf("горутин многовато: %d (base %d)", n, base)
}
}
}()


2. Трассировка с помощью go tool trace

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

func main() {
f, _ := os.Create("trace.out")
defer f.Close()
_ = trace.Start(f)
defer trace.Stop()

for i := 0; i < 10; i++ {
go func() { time.Sleep(500 * time.Millisecond) }()
}
time.Sleep(2 * time.Second)
}


go run .            # создаст trace.out
go tool trace trace.out


3. Контекстная отмена

Важно проксировать контекст через цепочку вызовов (например, в HTTP-хендлерах). Когда клиент прерывается или таймаут срабатывает — все дочерние горутины получают сигнал отмены и должны корректно завершаться.

func worker(ctx context.Context, jobs <-chan int) {
for {
select {
case <-ctx.Done():
log.Println("worker: cancelled")
return
case j, ok := <-jobs:
if !ok {
return
}
_ = j // делаем работу
}
}
}

func main() {
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()

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

go func() { // имитация продьюсера
for i := 0; i < 100; i++ {
select {
case <-ctx.Done():
close(jobs)
return
case jobs <- i:
}
}
}()

time.Sleep(3 * time.Second)
}


4. Интеграция goleak в тесты

В тестовой среде использовать goleak.VerifyTestMain или goleak.VerifyNone (внутри тестов) для автоматического обнаружения оставшихся горутин. Это помогает не допустить утечки до продакшена.

func TestMain(m *testing.M) { // глобальная проверка
goleak.VerifyTestMain(m)
}

func TestNoLeaks(t *testing.T) {
defer goleak.VerifyNone(t)

// Демонстрация «правильной» горутины
done := make(chan struct{})
go func() {
time.Sleep(10 * time.Millisecond)
close(done)
}()
<-done
}


5. Graceful shutdown

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

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

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍185🔥2
😀 Выберите свой класс

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

#GoGiggle
Please open Telegram to view this post
VIEW IN TELEGRAM
😁17👍2👾2