TGViewer
Go Update Go Update @go_update · 3.23K subscribers
Post #52 4.14K
⌛ runtime: special case timer channels.

У таймеров в Go есть интересная особенность: если на них не вызвать метод Stop то сборщик мусора не соберет их пока они не закончат свою работу или не будут явно остановлены. И если в случае функции time.After (которая возвращает канал) время сборки мусора отодвигалось до срабатывания таймера, то тикер time.Tick (функция которая тоже возвращает канал) не будет собран сборщиком мусора вообще никогда. Документация, конечно, объясняет эти моменты, но хотелось бы, что-бы рантайм делал свою работу а не оставлял мусор из-за особенностей работы языка. В частности из-за этой особенности time.Tick невозможно было применять в реальных долгоживущих приложениях.

Сейчас корректная работа с таймерами выглядит примерно вот так:


ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
// some other cases
// ...
case t := <-ticker.C:
fmt.Println("Current time: ", t)
return
}
}


Issue которое описывает проблему и потенциальное решение существует уже почти 10 лет. Более того, Расс хотел придумать и внедрить решение еще в Go 1.7. Однако время шло и к проблеме никто не возвращался.

В июле 2023го (спустя почти 9 лет) Расс наконец предложил решение в новом issue. Решение не успевало попасть в Go 1.21, но была надежда, что оно попадет в Go 1.22. Более того, в августе решение было одобрено, а так как PR уже был готов, была мысль, что оно попадет в мастер как можно скорее. Однако время продолжало идти, а PR висел и висел. К своему смущению, я был уверен, что проблема была решена в 1.22.

И вот наконец, момент настал: https://github.com/golang/go/commit/508bb17edd04479622fad263cd702deac1c49157. И даже документация теперь отражает, что вызов Stop на таймерах и тикерах больше не обязателен.

Ну что, как говорится «лучше поздно, чем никогда». Теперь time.Tick можно использовать в горячих местах. Еще одно место для легких правок в 1.23.

П.С. Если вам зачем-то нужно старое поведение, то переменная окружения GODEBUG=asynctimerchan=1 даст вашей программе старый вариант.
GitHub runtime: special case timer channels · Issue #8898 · golang/go Consider special-casing timer channels created with time.Ticker and time.After. Namely, such chans need to contain next fire time and period. Then receive from such looks like: func chanrecv(c *Hch...
  • 👍 46
  • 🔥 18
  • ❤ 2
More from @go_update
  1. Aug 22, 2026Об изоляции LLM Да, это ещё один пост про работу с Codex/Claude/GLM/Qwen/DeepSeek и прочая…
  2. Aug 11, 2026И вот эти два минуса выглядят нерешенными (на данный момент времени). Можно ли их решить в…
  3. Aug 11, 2026🎂 Вечерний пост о том, что сегодня мне исполнилось 34. Прошёл еще один год, а значит врем…
  4. Jul 13, 2026📝 testing: allow examples with any signature Небольшое «Quality of Life» предложение. Сут…
  5. May 14, 2026📝 net/http/httptest: synctest support Я уже писал про пакет synctest и его возможности. Э…
  6. May 13, 2026Я редко пишу сюда о вещах которые не относятся к Go, но тут у меня появилась хорошая стать…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →