🧑💻 Вы прошли техсобес. Задачи решены. Оффер получил другой
Это 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
👍10❤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👍7
Что выведет:
bytes.ContainsAny([]byte("hello"), "")Казалось бы, очевидно. Но разработчики разделились почти на четыре группы.
Подсказка: загляните в исходники стандартной библиотеки. Поведение
ContainsAny с пустым chars задокументировано — но интуиция здесь часто подводит.📍 Навигация: Вакансии • Задачи • Собесы
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Основная компетенция специалиста по Data Science – способность анализировать и интерпретировать данные, а математика является фундаментом для начала работы.
В карточках мы разбираем основные разделы математики, с которых стоит начать изучение специалисту по анализу данных.
Хотите подготовиться к офферу или подтянуть знания? Оставляйте заявку на наш курс по математике для Data Science 💙
P.S. Только до 31 мая на курс (и вообще на все программы Академии) действует
А как у вас дела с высшей математикой?
❤️ — Помню всё
🔥 — Знаю основы
🌚 — Ничего не знаю
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥4❤2🌚2
В стандартной библиотеке Go есть
sync.Pool. Штука простая по идее, но полезная на практике. Она позволяет переиспользовать объекты вместо того, чтобы каждый раз выделять под них новую память. Меньше аллокаций, меньше нагрузка на GC, выше производительность.Как это работает
Представьте скоростной принтер, который печатает 100 страниц в минуту. Было бы странно, если бы он перед каждой страницей бегал на склад за новой пачкой бумаги. Вместо этого у него есть лоток на 100 листов. Берём лист, печатаем, кладём обратно.
sync.Pool работает по тому же принципу.Вот как это выглядит в коде:
var paperPool = sync.Pool{
New: func() interface{} {
return new(Paper)
},
}
func printPage() {
page := paperPool.Get().(*Paper)
page.Reset()
defer paperPool.Put(page)
page.Print()
}Несколько важных моментов про
sync.Pool.У пула нет фиксированного размера. Вы можете класть и забирать объекты без жёстких ограничений. Но объект, который вы вернули в пул, может быть в любой момент удалён сборщиком мусора. Не стоит рассчитывать, что он там останется навсегда.
Ещё один момент. Объекты могут хранить состояние от предыдущего использования. Поэтому перед использованием или перед возвратом в пул их нужно сбрасывать. Если этого не делать, можно получить трудноуловимые баги с «грязными» данными.
Типобезопасная обёртка
sync.Pool хранит и возвращает interface{}. Это гибко, но не безопасно. Ничто не мешает положить в пул строку, а достать и попытаться привести к структуре. Приложение упадёт с паникой.Дженерики в Go позволяют обернуть
sync.Pool так, чтобы тип контролировался на этапе компиляции.type Pool[T any] struct {
internal sync.Pool
}
func NewPool[T any](newF func() T) *Pool[T] {
return &Pool[T]{
internal: sync.Pool{
New: func() interface{} {
return newF()
},
},
}
}Мы создали обёртку, привязанную к конкретному типу
T. Под капотом всё тот же sync.Pool с interface{}, но снаружи пользователь работает только с типом T.Теперь методы
Get и Put:func (p *Pool[T]) Get() T {
return p.internal.Get().(T)
}
func (p *Pool[T]) Put(x T) {
p.internal.Put(x)
}В
Get мы приводим interface{} к типу T без проверки ошибки. И это нормально. Наша обёртка гарантирует, что в пул попадают только значения типа T. Функция New создаёт T, метод Put принимает только T. Поэтому приведение типа p.internal.Get().(T) не вызовет панику при штатном использовании.Код остаётся чистым, типобезопасным и не требует ручных проверок на каждый
Get.Обёртка с дженериками убирает необходимость в ручном приведении типов и снижает риск ошибок. Решение занимает десяток строк, при этом полностью совместимо со стандартным
sync.Pool.📍 Навигация: Вакансии • Задачи • Собесы
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Осталось 7 дней до лета!
— Две уязвимости в golang.org/x/image
В пакете
golang.org/x/image исправлены две CVE. Первая вызывала панику при декодировании BMP с некорректным индексом палитры. Вторая позволяла через специально сформированный TIFF-файл заставить декодер потреблять непропорционально много ресурсов при распаковке PackBits.— Шесть уязвимостей в golang.org/x/net
В пакете
golang.org/x/net закрыты шесть CVE. Четыре связаны с XSS через ошибки HTML-парсера, одна позволяет устроить отказ в обслуживании при парсинге HTML, ещё одна открывает возможность обхода проверки доменных имён через некорректную обработку Punycode в пакете idna.— Vibe теперь и hiring
— Go 1.27 заморожен
📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM