⏳ time.Sleep игнорирует context — пишем свою версию, которая не игнорирует
Стандартный
Решение — написать свою функцию
Реализация
Создаём таймер и ждём, что произойдёт раньше: таймер сработает или контекст отменится:
Пример использования
Допустим, есть фоновая задача, которая выполняется в цикле с паузой между итерациями:
Когда контекст отменится,
Почему функция не возвращает ошибку
Первый вариант напрашивается сам собой — вернуть
Но на практике это усложняет вызывающий код без пользы. Отмена контекста — это не ошибка самого
Код после
Когда это пригодится
Функция полезна везде, где
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoDeep
Стандартный
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 — всё это становится отзывчивее к отмене без лишнего кода.📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
❤12
В зависимостях 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.Знаете где нет уязвимостей?
📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7❤4🔥4
Разберём базу: как получить текущее время, как создать конкретную дату и как форматировать и парсить строки. Всё на примерах из стандартной библиотеки, без сторонних зависимостей.
Текущее время и его компоненты
Всё начинается с
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/PMMST — сокращение таймзоны-07:00 — смещениеZ07:00 — Z для UTC, смещение для остальных📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9🤔2❤1😢1
21 мая(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Go-разработчика.
Как это будет:
Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Go-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.
Переходи в нашего бота, чтобы получить ссылку на эфир → @shortcut_go_bot Реклама.
О рекламодателе.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🥱2😁1
🧑💻 Вы прошли техсобес. Задачи решены. Оффер получил другой
Это vibe hiring — найм по ощущению, где решение принимается до того, как рекрутер посмотрел на ваши компетенции.
В статье — данные двух крупных исследований 2025–2026 годов, гендерная статистика по фидбеку с интервью и объяснение, почему субъективный найм бьёт по самой компании сильнее, чем по кандидату.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
Это vibe hiring — найм по ощущению, где решение принимается до того, как рекрутер посмотрел на ваши компетенции.
В статье — данные двух крупных исследований 2025–2026 годов, гендерная статистика по фидбеку с интервью и объяснение, почему субъективный найм бьёт по самой компании сильнее, чем по кандидату.
📍 Навигация: Вакансии • Задачи • Собесы
Please open Telegram to view this post
VIEW IN TELEGRAM
❤3😢2🥱2
Разберём тип
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"
📍 Навигация: Вакансии • Задачи • Собесы
#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 мая — очень ждём именно тебя!
Команда GigaChat зовёт на One Day Offer амбициозных Java-разработчиков, которые готовы создавать AI‑продукты уровня BigTech и стать частью крупнейшего AI-комьюнити.
Если ты дружишь с Java (версии 8–25), ладишь со Spring и Hibernate, а PostgreSQL и ClickHouse для тебя — не просто слова, переходи по ссылке и занимай слот на One Day Offer.
Встречаемся 23 мая — очень ждём именно тебя!
🥱6😁1
Senior Golang Developer — офис в Сербии
Senior Golang-разработчик — от 300 000 ₽, удаленно по Москве
Golang-разработчик — до 150 000 ₽, удаленно или гибрид в Москве
#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:
🛠 Что внутри методички (комбо из 3 статей + код):
🍒 Вишенка на торте: готовый SKILL для агента, который делает ревью вашего проекта, находит анти-паттерны и предотвращает низкое попадание в кэш.
— Забрать комбо-материалы на GitHub
P.S. Если хотите послушать Сергея вживую — ловите его на конференциях Kode Waves (май), Conversations AI и Highload Spb (июнь).
🎁 Акция в честь старта продаж!
Прямо сейчас при покупке Инженерного трека вы получаете полный доступ к материалам курса «Разработка ИИ-агентов» в подарок.
👉 Забрать 2 курса по цене 1 и начать обучение
Знакомьтесь, Сергей Нотевский. 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. Тесты становятся быстрыми и детерминированными.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9❤2
Команда Go объявила о начале заморозки релиза Go 1.27. С этого момента новые фичи и оптимизации не принимаются до следующего цикла. Багфиксы по-прежнему можно отправлять.
Release Candidate 1 запланирован на вторую неделю июня. Сейчас основной приоритет — закрытие issues, блокирующих RC 1.
У команды 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 по 5 июня Podlodka Go Crew совместно с 2ГИС проведут сезон «Лучшие практики в Go», где участники разберут, как делать сервисы, которые нормально работают под нагрузкой и остаются управляемыми.
В программе:
🧩 Паттерны в Go: что работает, а что приходится переосмыслять
⚡️ Рост Go-сервисов под нагрузкой — путь от прототипа до миллионов RPS
🛠 Тестирование: от базовых сценариев до выстраивания пирамиды тестов
🔍 Живой разбор кейсов межсервисного взаимодействия
🤝 Обсуждение влияния AI на процессы разработки с экспертами Go-сообщества
Формат — пять дней живых Zoom-сессий утром и вечером, закрытое сообщество в Telegram и общение со спикерами.
Конференция подойдет тем, кто хочет вместе с коллегами обсудить реальные задачи в работе с Go — без высокоуровневых абстракций, на уровне конкретных инструментов, подходов и решений, которые используются в продакшене.
👉 Билеты по early-bird цене и программа ждут здесь: https://podlodka.io/gocrew
👾1
⏰ Пакет time в Go: таймеры, тикеры и паттерны
Стандартный
Таймеры
Таймер можно остановить до срабатывания через
Тикеры
Таймауты через context
В продакшене таймауты реализуют через
Замер времени выполнения
Простая обёртка через
Rate limiter
Простейший вариант на
Retry с экспоненциальным backoff
Пауза удваивается после каждой неудачи, но не превышает
Если переходите с других языков — запомните референсную дату
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoDeep
Стандартный
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().📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5👾1
Небольшое изменение в 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'и с учётом нового дефолтного представления.
📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍6
Как устроены продукты, которые задают тренды?
Т-Банк готовит летний фест для тех, кому важно не просто слушать, а разбираться, как реально устроены продукты
20 июня «Сезон кода» собирает разработчиков, аналитиков и продактов в Санкт-Петербурге, чтобы показать, как создаются продукты — от первых гипотез до продакшена.
Вас ждут:
— прикладные доклады команд Т-Банка и других компаний про архитектуру, бэкенд и интеграции;
— демо-зоны с ключевыми платформенными и коммуникационными сервисами и графовой аналитикой;
— продуктовый стрим «Продуктовая кухня»: разберем, как данные превращаются в решения, а гипотезы — в рост продукта и ценность для пользователя;
— формат, где знакомства происходят прямо по ходу программы.
А еще — баскетбольная площадка, пинг-понг и большое афтепати с диджеем.
Фест пройдет в ИТ-хабе Группы компаний «Т-Технологии».
Количество мест ограничено — успейте зарегистрироваться
Т-Банк готовит летний фест для тех, кому важно не просто слушать, а разбираться, как реально устроены продукты
20 июня «Сезон кода» собирает разработчиков, аналитиков и продактов в Санкт-Петербурге, чтобы показать, как создаются продукты — от первых гипотез до продакшена.
Вас ждут:
— прикладные доклады команд Т-Банка и других компаний про архитектуру, бэкенд и интеграции;
— демо-зоны с ключевыми платформенными и коммуникационными сервисами и графовой аналитикой;
— продуктовый стрим «Продуктовая кухня»: разберем, как данные превращаются в решения, а гипотезы — в рост продукта и ценность для пользователя;
— формат, где знакомства происходят прямо по ходу программы.
А еще — баскетбольная площадка, пинг-понг и большое афтепати с диджеем.
Фест пройдет в ИТ-хабе Группы компаний «Т-Технологии».
Количество мест ограничено — успейте зарегистрироваться
❤🔥1🥱1