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

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

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

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

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

#WXSSA
Download Telegram
time.Sleep игнорирует context — пишем свою версию, которая не игнорирует

Стандартный time.Sleep() в Go ничего не знает про контекст. Если вы поставили паузу на 30 секунд, а контекст отменился через 2 — функция всё равно будет ждать все 30. Это проблема в любом коде, где важна отзывчивость на отмену: фоновые воркеры, периодические задачи, graceful shutdown.

Решение — написать свою функцию Sleep, которая завершится досрочно, если контекст будет отменён.

Реализация

Создаём таймер и ждём, что произойдёт раньше: таймер сработает или контекст отменится:
func Sleep(ctx context.Context, d time.Duration) {
timer := time.NewTimer(d)
defer timer.Stop()

select {
case <-ctx.Done():
return
case <-timer.C:
return
}
}


select блокирует горутину до тех пор, пока один из каналов не станет готов. Если контекст отменяется раньше таймера — выходим сразу. Если таймер срабатывает первым — выходим как обычный Sleep. В обоих случаях defer timer.Stop() корректно освобождает ресурсы.

Пример использования

Допустим, есть фоновая задача, которая выполняется в цикле с паузой между итерациями:
func Job(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
default:
doWork()
Sleep(ctx, 10 * time.Second)
}
}
}


Когда контекст отменится, Sleep завершится мгновенно. На следующей итерации цикл проверит ctx.Done() и выйдет. Без нашей функции воркер бы завис в time.Sleep на оставшееся время, а сервис не мог бы корректно остановиться.

Почему функция не возвращает ошибку

Первый вариант напрашивается сам собой — вернуть ctx.Err() при отмене контекста:
func Sleep(ctx context.Context, d time.Duration) error {
timer := time.NewTimer(d)
defer timer.Stop()

select {
case <-ctx.Done():
return ctx.Err()
case <-timer.C:
return nil
}
}


Но на практике это усложняет вызывающий код без пользы. Отмена контекста — это не ошибка самого Sleep. Это сигнал для всей цепочки выполнения.

Код после Sleep обычно тоже проверяет контекст, и если он отменён — тоже завершается. Обрабатывать ошибку именно от Sleep нет смысла, поэтому сигнатура без error делает функцию проще в использовании.

Когда это пригодится

Функция полезна везде, где time.Sleep стоит внутри цикла или последовательности операций, привязанных к контексту. Фоновые джобы, ретраи с задержкой, периодические опросы, rate limiting — всё это становится отзывчивее к отмене без лишнего кода.

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

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
12
⌨️ Cканер уязвимостей для Go от команды Go

В зависимостях Go проекта могут быть известные уязвимости. Можно узнать об этом из новостей, а можно проверять автоматически. govulncheck — официальный инструмент от команды Go, который находит уязвимости в коде и зависимостях вашего проекта.

Чем полезен

Обычные сканеры зависимостей работают грубо. Они сверяют список пакетов с базой CVE и сообщают обо всём, что нашли. Даже если уязвимая функция в вашем коде вообще не вызывается.

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

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

Как использовать

Самый простой сценарий. Переходим в директорию модуля и сканируем все пакеты.
cd my-module
govulncheck ./...


Если уязвимостей нет, govulncheck выведет короткое сообщение. Если есть, покажет описание каждой уязвимости и краткий call stack, чтобы было понятно, как именно ваш код вызывает уязвимую функцию.

Вывод может выглядеть так:
main.go:42:3: mypackage.main calls golang.org/x/text/language.Parse


Чтобы увидеть полный стек вызовов, добавьте флаг:
govulncheck -show traces ./...


Для подробного вывода с прогрессом:
govulncheck -show verbose ./...


Сканирование бинарных файлов

govulncheck умеет проверять не только исходный код, но и скомпилированные бинарники. Для этого используется флаг -mode binary:
govulncheck -mode binary $HOME/go/bin/my-go-program


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

Есть ещё режим -mode extract. Он извлекает из бинарника минимальную информацию, нужную для анализа, и сохраняет её в отдельный файл. Этот файл обычно гораздо меньше оригинального бинарника, и его тоже можно передать в govulncheck с флагом -mode binary.

Форматы вывода

Помимо текстового вывода, govulncheck поддерживает несколько машиночитаемых форматов. JSON для потоковой обработки, SARIF для интеграции с CI/CD и инструментами анализа, VEX (Vulnerability EXchange) по спецификации OpenVEX.

Что стоит учитывать

Инструмент анализирует вызовы через указатели на функции и интерфейсы консервативно. Это иногда приводит к ложным срабатываниям. Вызовы через пакет reflect статическому анализу не видны, поэтому уязвимости, достижимые только через рефлексию, в отчёт не попадут. То же касается unsafe.

На момент версии v1.1.4 нет встроенного механизма подавления конкретных находок. Задача на это ведётся в https://go.dev/issue/61211.

govulncheck полезен тем, что даёт конкретику. Вместо списка «у вас есть пакет с CVE» он показывает, вызывается ли уязвимая функция в вашем коде. Встраивается в CI, понимает бинарники, выводит в SARIF и JSON. Официальный инструмент, поддерживается командой Go.

Знаете где нет уязвимостей? ➡️ В нашей новостной рассылке

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

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍74🔥4
Пакет time в Go: основы, создание и форматирование

Разберём базу: как получить текущее время, как создать конкретную дату и как форматировать и парсить строки. Всё на примерах из стандартной библиотеки, без сторонних зависимостей.

Текущее время и его компоненты

Всё начинается с time.Now(). Этот вызов возвращает структуру time.Time с текущим временем:
now := time.Now()
fmt.Println(now) // 2024-01-15 10:30:00.123456789 -0500 EST


Из неё можно вытащить любой компонент через методы:
now.Year()       // 2024
now.Month() // January
now.Day() // 15
now.Hour() // 10
now.Minute() // 30
now.Second() // 0
now.Weekday() // Monday
now.YearDay() // 15 (день в году)


Для интеграций часто нужны Unix-таймстемпы:
now.Unix()      // 1705329000 (секунды)
now.UnixMilli() // 1705329000123 (миллисекунды)
now.UnixNano() // 1705329000123456789 (наносекунды)


Создание конкретной даты

Если нужно задать дату руками, используйте time.Date():
t := time.Date(2024, time.January, 15, 10, 30, 0, 0, time.UTC)


Аргументы по порядку: год, месяц, день, час, минута, секунда, наносекунда, таймзона.

Из Unix-таймстемпа:
t := time.Unix(1705329000, 0)
t := time.UnixMilli(1705329000123)


Из строки через парсинг:
t, err := time.Parse("2006-01-02", "2024-01-15")
t, err := time.Parse(time.RFC3339, "2024-01-15T10:30:00Z")


Нулевое значение time.Time можно проверить методом IsZero():
var t time.Time
fmt.Println(t.IsZero()) // true


Форматирование и парсинг

Тут Go отличается от большинства языков. Вместо %Y-%m-%d или yyyy-MM-dd используется референсная дата: Mon Jan 2 15:04:05 MST 2006. Запоминается просто: 1/2 3:4:5 2006.

Форматируем в строку:
now.Format("2006-01-02")          // 2024-01-15
now.Format("02/01/2006") // 15/01/2024
now.Format("January 2, 2006") // January 15, 2024
now.Format("15:04:05") // 10:30:00
now.Format("3:04 PM") // 10:30 AM


Есть готовые константы:
now.Format(time.RFC3339)  // 2024-01-15T10:30:00-05:00
now.Format(time.Kitchen) // 10:30AM
now.Format(time.DateOnly) // 2024-01-15 (Go 1.20+)
now.Format(time.TimeOnly) // 10:30:00 (Go 1.20+)


Парсинг работает зеркально: передаёте тот же шаблон и строку:
t, err := time.Parse("2006-01-02", "2024-01-15")
t, err := time.Parse("01/02/2006 3:04 PM", "01/15/2024 10:30 AM")


Если нужно парсить с привязкой к таймзоне, используйте time.ParseInLocation():
loc, _ := time.LoadLocation("America/New_York")
t, err := time.ParseInLocation("2006-01-02 15:04", "2024-01-15 10:30", loc)


Шпаргалка по символам формата

2006 — 4-значный год
06 — 2-значный год
01 — месяц с нулём (01)
1 — месяц без нуля (1)
January — полное название месяца
Jan — сокращённое название
02 — день с нулём
2 — день без нуля
Monday — полное название дня недели
Mon — сокращённое
15 — час в 24-часовом формате
03 — час в 12-часовом с нулём
3 — час в 12-часовом без нуля
04 — минуты
05 — секунды
PM — AM/PM
MST — сокращение таймзоны
-07:00 — смещение
Z07:00 — Z для UTC, смещение для остальных

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

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤔21😢1
🔍Тестовое собеседование с Go ТехЛидом из Wildberries & Russ в этот четверг

21 мая(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Go-разработчика.

Как это будет:
📂 Рамиль Мясоутов, ТехЛид из WildBerries, ex-Купер будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Рамиль будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Рамилю

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Go-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир →
@shortcut_go_bot Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🥱2😁1
🧑‍💻 Вы прошли техсобес. Задачи решены. Оффер получил другой

Это vibe hiring — найм по ощущению, где решение принимается до того, как рекрутер посмотрел на ваши компетенции.

В статье — данные двух крупных исследований 2025–2026 годов, гендерная статистика по фидбеку с интервью и объяснение, почему субъективный найм бьёт по самой компании сильнее, чем по кандидату.

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

🐸 Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
3😢2🥱2
Пакет time в Go: длительность, арифметика и таймзоны

Разберём тип Duration, операции сложения и вычитания дат, сравнение и работу с часовыми поясами.

Duration

time.Duration — это промежуток времени в наносекундах. Создаётся через умножение на константы пакета:
d := 5 * time.Second
d := 2*time.Hour + 30*time.Minute
d := time.Duration(500) * time.Millisecond


Можно распарсить из строки:
d, err := time.ParseDuration("1h30m")
d, err := time.ParseDuration("2h45m30s")
d, err := time.ParseDuration("100ms")
d, err := time.ParseDuration("-1h") // отрицательная длительность


У Duration есть методы для конвертации в нужные единицы:
d := 2*time.Hour + 30*time.Minute + 45*time.Second
d.Hours() // 2.5125
d.Minutes() // 150.75
d.Seconds() // 9045
d.Milliseconds() // 9045000
d.String() // 2h30m45s


Доступные константы:
time.Nanosecond  // 1
time.Microsecond // 1000 наносекунд
time.Millisecond // 1000 микросекунд
time.Second // 1000 миллисекунд
time.Minute // 60 секунд
time.Hour // 60 минут


Арифметика времени

Добавить Duration к time.Time:
now := time.Now()
future := now.Add(24 * time.Hour)
future := now.Add(2*time.Hour + 30*time.Minute)


Для календарных операций (где важны границы месяцев и лет) есть AddDate():
nextMonth := now.AddDate(0, 1, 0)  // +1 месяц
nextYear := now.AddDate(1, 0, 0) // +1 год
lastWeek := now.AddDate(0, 0, -7) // -7 дней


Разница между двумя моментами:
diff := future.Sub(now) // возвращает Duration
fmt.Println(diff.Hours())


Два удобных сокращения:
elapsed := time.Since(start)      // то же, что time.Now().Sub(start)
remaining := time.Until(deadline) // то же, что deadline.Sub(time.Now())


Сравнение

Методы Before(), After() и Equal() делают то, что ожидаешь:
t1 := time.Now()
t2 := t1.Add(time.Hour)

t1.Before(t2) // true
t1.After(t2) // false
t1.Equal(t2) // false


Начиная с Go 1.20 появился метод Compare(), который возвращает -1, 0 или 1:
cmp := t1.Compare(t2) // -1 (t1 раньше t2)


Таймзоны

Загрузка таймзоны по имени IANA:
nyc, err := time.LoadLocation("America/New_York")
tokyo, err := time.LoadLocation("Asia/Tokyo")
utc := time.UTC
local := time.Local


Конвертация между зонами:
now := time.Now()
utcTime := now.UTC()
nycTime := now.In(nyc)


Создание времени сразу в нужной зоне:
t := time.Date(2024, 1, 15, 10, 30, 0, 0, nyc)


Получить информацию о текущей зоне:
name, offset := now.Zone()
fmt.Println(name, offset) // EST -18000 (смещение в секундах)


Если нужна зона с фиксированным смещением:
est := time.FixedZone("EST", -5*60*60)


Важный момент: time.LoadLocation() ищет данные IANA в системе. Если на сервере нет файла tzdata, вызов вернёт ошибку. В Go 1.15 появился пакет time/tzdata, который вшивает базу зон прямо в бинарник. Достаточно импорта:
import _ "time/tzdata"


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

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9👏1
Твой код — в сердце мощного ИИ! 💚

Команда GigaChat зовёт на One Day Offer амбициозных Java-разработчиков, которые готовы создавать AI‑продукты уровня BigTech и стать частью крупнейшего AI-комьюнити.

Если ты дружишь с Java (версии 8–25), ладишь со Spring и Hibernate, а PostgreSQL и ClickHouse для тебя — не просто слова, переходи по ссылке и занимай слот на One Day Offer.

Встречаемся 23 мая — очень ждём именно тебя!
🥱6😁1
🤨 Топ-вакансий для Go-разработчиков за неделю

Senior Golang Developer — офис в Сербии

Senior Golang-разработчик — от 300 000 ₽, удаленно по Москве

Golang-разработчик — до 150 000 ₽, удаленно или гибрид в Москве

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

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

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
😁2🌚1
🔥 База по экономике токенов и кэшированию от AI Platform Lead из Bitrix24

Знакомьтесь, Сергей Нотевский. AI Platform Lead в Bitrix24.

Он один из ключевых экспертов нашего курса AgentOps. На своих лекциях он детально разбирает экономику AI-агентов, кэширование токенов, LLM-инфраструктуру и вывод генеративных систем в стабильный прод.

Мы попросили Сергея поделиться материалами для тех, кто хочет оптимизировать косты на LLM в проде. Сохраняйте методичку по prefix cache метрике, которая напрямую влияет на ваши деньги.

Как говорят создатели Manus:
“KV-cache hit rate is the single most important metric for a production-stage AI agent.”


🛠 Что внутри методички (комбо из 3 статей + код):
Экономика кэширования — особенности провайдеров и как правильно считать затраты.

Частые анти-паттерны — почему ваш кэш постоянно сбрасывается и вы платите больше.

Кэш в AI-агентах — специфика работы с памятью в автономных системах.


🍒 Вишенка на торте: готовый SKILL для агента, который делает ревью вашего проекта, находит анти-паттерны и предотвращает низкое попадание в кэш.

Забрать комбо-материалы на GitHub

P.S. Если хотите послушать Сергея вживую — ловите его на конференциях Kode Waves (май), Conversations AI и Highload Spb (июнь).

🎁 Акция в честь старта продаж!

Прямо сейчас при покупке Инженерного трека вы получаете полный доступ к материалам курса «Разработка ИИ-агентов» в подарок.

👉 Забрать 2 курса по цене 1 и начать обучение
😉 Тесты для конкурентного кода

Каждый, кто писал тесты для конкурентного Go, знает эту боль. Нужно проверить, что что-то произошло (или не произошло) после работы горутины. А единственный способ это сделать — воткнуть time.Sleep и надеяться, что на CI этого хватит.

Выглядело это примерно так:
func TestTimeout(t *testing.T) {
// ... настраиваем логику таймаута ...

time.Sleep(10 * time.Millisecond) // авось хватит

if !timedOut {
t.Fatal("expected timeout, got none")
}
}


10 миллисекунд на один тест — мелочь. Но когда таких тестов сотни, набегают секунды пустого ожидания. А на нагруженном CI раннере 10ms иногда недостаточно, и тест становится flaky.

Что делает synctest

Пакет testing/synctest появился экспериментально в Go 1.24 за флагом GOEXPERIMENT=synctest. В Go 1.25 он вышел в GA с обновлённым API — флаг больше не нужен. Вместо старого synctest.Run используем synctest.Test. Старый API удалён в Go 1.26.

Пакет решает проблему двумя механизмами.

Bubble. synctest.Test() оборачивает тест в изолированную среду. Все горутины, запущенные внутри, принадлежат этому «пузырю».

Виртуальное время. Внутри пузыря time.Sleep, таймеры и тикеры работают на фейковых часах. Реальное время не идёт. Часы сдвигаются только тогда, когда все горутины в пузыре заблокированы и ждут. Тест с пятисекундным таймаутом выполняется за микросекунды.

`synctest.Wait()` блокирует выполнение, пока все остальные горутины в пузыре не окажутся в состоянии устойчивой блокировки. После возврата из Wait() мы точно знаем, что система обработала всё, что могла.

Вот тот же тест, переписанный на synctest:
import "testing/synctest"

func TestTimeout(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
const timeout = 5 * time.Second
ctx, cancel := context.WithTimeout(
context.Background(), timeout,
)
defer cancel()

time.Sleep(timeout - time.Nanosecond)
synctest.Wait()
if err := ctx.Err(); err != nil {
t.Fatalf("context expired early: %v", err)
}

time.Sleep(time.Nanosecond)
synctest.Wait()
if ctx.Err() != context.DeadlineExceeded {
t.Fatalf("expected DeadlineExceeded, got %v", ctx.Err())
}
})
}


Никакого реального ожидания. Никаких flaky. Никаких изменений в тестируемом коде.

Что считается «устойчивой блокировкой»

Не все блокирующие операции равны. synctest.Wait() учитывает только те, которые могут быть разблокированы исключительно горутинами внутри пузыря.

Учитываются: отправка и получение из каналов, созданных внутри пузыря, time.Sleep, sync.Cond.Wait, sync.WaitGroup.Wait.

Не учитываются: sync.Mutex (обычно захватывается ненадолго), сетевые вызовы и чтение файлов (их может разблокировать ядро ОС).

Сетевые тесты

Для тестирования сетевого взаимодействия внутри пузыря используем net.Pipe() — это in-memory соединения, которые synctest считает устойчиво блокирующими:
func TestServerHandshake(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
serverConn, clientConn := net.Pipe()
defer serverConn.Close()
defer clientConn.Close()

go runServer(serverConn)
go runClient(clientConn)
synctest.Wait()
// Все горутины заблокированы — хендшейк завершён
})
}


Запуск

На Go 1.25+ никаких дополнительных флагов:
go test ./...


Если вы до сих пор боретесь с flaky-тестами в конкурентном коде, synctest убирает главную причину — гадание на time.Sleep. Тесты становятся быстрыми и детерминированными.

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

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍92
🥶 Go 1.27 уже в release freeze

Команда Go объявила о начале заморозки релиза Go 1.27. С этого момента новые фичи и оптимизации не принимаются до следующего цикла. Багфиксы по-прежнему можно отправлять.

Release Candidate 1 запланирован на вторую неделю июня. Сейчас основной приоритет — закрытие issues, блокирующих RC 1.

➡️ Источник

У команды Go есть новости, а у нас есть новостная рассылка

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

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍1
⚙️Практикуем Go вместе с Podlodka Go Crew

Сервис вроде работает, но любая новая нагрузка быстро вскрывает проблемы: растут задержки, появляются утечки памяти, а временные решения слишком часто закрепляются в архитектуре. Знакомо?

С 1 по 5 июня Podlodka Go Crew совместно с 2ГИС проведут сезон «Лучшие практики в Go», где участники разберут, как делать сервисы, которые нормально работают под нагрузкой и остаются управляемыми.

В программе:


🧩 Паттерны в Go: что работает, а что приходится переосмыслять

⚡️ Рост Go-сервисов под нагрузкой — путь от прототипа до миллионов RPS

🛠 Тестирование: от базовых сценариев до выстраивания пирамиды тестов

🔍 Живой разбор кейсов межсервисного взаимодействия

🤝 Обсуждение влияния AI на процессы разработки с экспертами Go-сообщества

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

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

👉 Билеты по early-bird цене и программа ждут здесь: https://podlodka.io/gocrew

А по нашему промокоду goproglib получите скидку🎁
👾1
Пакет time в Go: таймеры, тикеры и паттерны

Стандартный time закрывает почти все задачи по работе со временем без сторонних библиотек. Разберём основные примитивы и паттерны.

Таймеры

time.NewTimer() срабатывает один раз через заданный интервал:
timer := time.NewTimer(2 * time.Second)
<-timer.C
fmt.Println("Timer fired!")


Таймер можно остановить до срабатывания через timer.Stop() и перезапустить через timer.Reset().

time.After() — сокращение без доступа к таймеру. time.AfterFunc() вызывает функцию в отдельной горутине.

Тикеры

time.NewTicker() срабатывает повторно через равные интервалы. Всегда вызывайте Stop(), иначе горутина утечёт:
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

for i := 0; i < 5; i++ {
<-ticker.C
fmt.Println("Tick", i)
}


Таймауты через context

В продакшене таймауты реализуют через context — это позволяет пробросить отмену по всей цепочке вызовов:
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

select {
case result := <-doWork(ctx):
fmt.Println("Result:", result)
case <-ctx.Done():
fmt.Println("Timeout:", ctx.Err())
}


Замер времени выполнения

Простая обёртка через defer. Первый вызов запоминает старт, возвращённое замыкание откладывается и печатает разницу:
func measureTime(name string) func() {
start := time.Now()
return func() {
fmt.Printf("%s took %v\n", name, time.Since(start))
}
}

defer measureTime("main")()


Rate limiter

Простейший вариант на time.Tick() — один запрос в секунду:
limiter := time.Tick(time.Second)
for req := range requests {
<-limiter
process(req)
}


Retry с экспоненциальным backoff

Пауза удваивается после каждой неудачи, но не превышает maxBackoff. В продакшене стоит добавить jitter, чтобы клиенты не нагружали сервер одновременно:
backoff := 100 * time.Millisecond
maxBackoff := 10 * time.Second

for i := 0; i < maxRetries; i++ {
if err := fn(); err == nil {
return nil
}
time.Sleep(backoff)
backoff *= 2
if backoff > maxBackoff {
backoff = maxBackoff
}
}


Если переходите с других языков — запомните референсную дату 1/2 3:4:5 2006 и не забывайте вызывать ticker.Stop().

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

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
5👾1
📊 pprof открывается с Flame Graph по умолчанию

Небольшое изменение в Go 1.26, которое заметно влияет на процесс отладки производительности.

До версии 1.26 команда go tool pprof -http=:8080 открывала top-down tree view. Чтобы переключиться на Flame Graph, нужно было сделать это вручную. На практике многие просто оставались в tree view, потому что оно открывалось первым.

Теперь pprof сразу показывает flame graph. Разница существенная. Flame graph визуально отображает весь стек вызовов: широкие блоки означают медленные функции, высокие столбцы показывают глубокие цепочки вызовов. Tree view содержит ту же информацию, но в виде текстового списка, который требует больше усилий для анализа.

Если в вашей команде регулярно занимаются отладкой производительности, обновите runbook'и и incident playbook'и с учётом нового дефолтного представления.

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

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍6
Как устроены продукты, которые задают тренды?

Т-Банк готовит летний фест для тех, кому важно не просто слушать, а разбираться, как реально устроены продукты

20 июня «Сезон кода» собирает разработчиков, аналитиков и продактов в Санкт-Петербурге, чтобы показать, как создаются продукты — от первых гипотез до продакшена.

Вас ждут:

— прикладные доклады команд Т-Банка и других компаний про архитектуру, бэкенд и интеграции;
— демо-зоны с ключевыми платформенными и коммуникационными сервисами и графовой аналитикой;
— продуктовый стрим «Продуктовая кухня»: разберем, как данные превращаются в решения, а гипотезы — в рост продукта и ценность для пользователя;
— формат, где знакомства происходят прямо по ходу программы.

А еще — баскетбольная площадка, пинг-понг и большое афтепати с диджеем.
Фест пройдет в ИТ-хабе Группы компаний «Т-Технологии».
Количество мест ограничено — успейте зарегистрироваться
❤‍🔥1🥱1