en
Feedback
Библиотека Go-разработчика | Golang

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

Open in Telegram

Все самое полезное для Go-разработчика в одном канале. Покажем, как запустить своего ии-агента: https://clc.to/tvpm По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0 #WXSSA

Show more

📈 Analytical overview of Telegram channel Библиотека Go-разработчика | Golang

Channel Библиотека Go-разработчика | Golang (@goproglib) in the Russian language segment is an active participant. Currently, the community unites 23 989 subscribers, ranking 5 684 in the Technologies & Applications category and 27 922 in the Russia region.

📊 Audience metrics and dynamics

Since its creation on невідомо, the project has demonstrated rapid growth, gathering an audience of 23 989 subscribers.

According to the latest data from 12 June, 2026, the channel demonstrates stable activity. Although there has been a change in the number of participants by 38 over the last 30 days and by -8 over the last 24 hours, overall reach remains high.

  • Verification status: Not verified
  • Engagement rate (ER): The average audience engagement rate is 10.75%. Within the first 24 hours after publication, content typically collects 7.57% reactions from the total number of subscribers.
  • Post reach: On average, each post receives 2 579 views. Within the first day, a publication typically gains 1 817 views.
  • Reactions and interaction: The audience actively supports content: the average number of reactions per post is 9.
  • Thematic interests: Content is focused on key topics such as навигация, лучшее_из_библиотеки_2025, git, string, golive.

📝 Description and content policy

The author describes the resource as a platform for expressing subjective opinions:
Все самое полезное для Go-разработчика в одном канале. Покажем, как запустить своего ии-агента: https://clc.to/tvpm По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0 #...

Thanks to the high frequency of updates (latest data received on 13 June, 2026), the channel maintains relevance and a high level of publication reach. Analytics show that the audience actively interacts with content, making it an important point of influence in the Technologies & Applications category.

23 989
Subscribers
-824 hours
-317 days
+3830 days
Attracting Subscribers
June '26
June '26
+70
in 2 channels
May '26
+288
in 3 channels
Get PRO
April '26
+249
in 1 channels
Get PRO
March '26
+216
in 1 channels
Get PRO
February '26
+487
in 7 channels
Get PRO
January '26
+346
in 3 channels
Get PRO
December '25
+370
in 4 channels
Get PRO
November '25
+384
in 4 channels
Get PRO
October '25
+331
in 2 channels
Get PRO
September '25
+290
in 0 channels
Get PRO
August '25
+316
in 4 channels
Get PRO
July '25
+317
in 2 channels
Get PRO
June '25
+315
in 0 channels
Get PRO
May '25
+391
in 5 channels
Get PRO
April '25
+358
in 4 channels
Get PRO
March '25
+625
in 53 channels
Get PRO
February '25
+527
in 35 channels
Get PRO
January '25
+517
in 37 channels
Get PRO
December '24
+591
in 40 channels
Get PRO
November '24
+605
in 52 channels
Get PRO
October '24
+499
in 36 channels
Get PRO
September '24
+676
in 36 channels
Get PRO
August '24
+580
in 36 channels
Get PRO
July '24
+586
in 37 channels
Get PRO
June '24
+467
in 29 channels
Get PRO
May '24
+674
in 35 channels
Get PRO
April '24
+771
in 36 channels
Get PRO
March '24
+901
in 31 channels
Get PRO
February '24
+729
in 31 channels
Get PRO
January '24
+863
in 27 channels
Get PRO
December '23
+850
in 29 channels
Get PRO
November '23
+608
in 10 channels
Get PRO
October '23
+697
in 25 channels
Get PRO
September '23
+723
in 0 channels
Get PRO
August '23
+648
in 0 channels
Get PRO
July '23
+503
in 0 channels
Get PRO
June '23
+422
in 0 channels
Get PRO
May '23
+568
in 0 channels
Get PRO
April '23
+365
in 0 channels
Get PRO
March '23
+841
in 0 channels
Get PRO
February '23
+392
in 0 channels
Get PRO
January '23
+395
in 0 channels
Get PRO
December '22
+384
in 0 channels
Get PRO
November '22
+491
in 0 channels
Get PRO
October '22
+256
in 0 channels
Get PRO
September '22
+292
in 0 channels
Get PRO
August '22
+394
in 0 channels
Get PRO
July '22
+472
in 0 channels
Get PRO
June '22
+443
in 0 channels
Get PRO
May '22
+176
in 0 channels
Get PRO
April '22
+328
in 0 channels
Get PRO
March '22
+242
in 0 channels
Get PRO
February '22
+135
in 0 channels
Get PRO
January '22
+236
in 0 channels
Get PRO
December '21
+245
in 0 channels
Get PRO
November '21
+219
in 0 channels
Get PRO
October '21
+215
in 0 channels
Get PRO
September '21
+290
in 0 channels
Get PRO
August '21
+298
in 0 channels
Get PRO
July '21
+281
in 0 channels
Get PRO
June '21
+196
in 0 channels
Get PRO
May '21
+389
in 0 channels
Get PRO
April '21
+336
in 0 channels
Get PRO
March '21
+280
in 0 channels
Get PRO
February '21
+258
in 0 channels
Get PRO
January '21
+262
in 0 channels
Get PRO
December '20
+6 566
in 0 channels
Date
Subscriber Growth
Mentions
Channels
13 June0
12 June+6
11 June+9
10 June+3
09 June+8
08 June+1
07 June+7
06 June+2
05 June+10
04 June+4
03 June+7
02 June+8
01 June+5
Channel Posts
💻 3 курса по цене одного — собери стек для оффера в топовую IT-компанию Для следующего карьерного шага мало писать код. Рабо
💻 3 курса по цене одного — собери стек для оффера в топовую IT-компанию Для следующего карьерного шага мало писать код. Работодатели ждут не только знания языка, но и понимания архитектуры, алгоритмов, автоматизации, AI-инструментов и агентных систем. Одно направление закрывает только часть задачи. Поэтому сейчас мы предлагаем освоить сразу несколько востребованных навыков — выбери любой курс и получи доступ еще к двум бесплатно 🔥 Собери стек навыков под свою цель: 🔹 подготовка к сильным компаниям (алгоритмы, архитектура); 🔹 переход в AI-направление (ИИ-агенты, AgentOps); 🔹 развитие в ML и Data Science (математика, основы ML); 🔹 новый оффер и рост дохода. Полученные знания применяешь в работе уже во время обучения. ⏳ Акция действует 48 часов — 13 и 14 июня. 👉 Переходи на сайт, выбирай курсы и оставляй заявку — за 10 минут поможем собрать комплект под твою цель.

2
💡 Постоянная память для ИИ-агентов в коде ИИ-агент в редакторе теряет весь контекст, как только закрывается сессия. Вы объяснили архитектуру проекта, разобрали хитрый баг, договорились о соглашениях в коде, а на следующий день агент снова чистый лист. Приходится пересказывать одно и то же. Engram это один бинарник на Go, который хранит память агента в локальной базе SQLite с полнотекстовым поиском FTS5. Внешних зависимостей нет. Не нужен ни Node.js, ни Python, ни Docker. Файл базы лежит в ~/.engram/engram.db, и это единственное место, где живут данные. Доступ к памяти открыт сразу через несколько интерфейсов. Есть CLI для ручных команд, HTTP API, MCP-сервер для агентов и текстовый интерфейс TUI для просмотра. Работает с любым агентом, который поддерживает MCP. В списке Claude Code, OpenCode, Gemini CLI, Codex, VS Code с Copilot, Cursor, Windsurf и другие. 🛠 Как работает Агент закончил осмысленную работу, например починил баг или принял архитектурное решение. Он вызывает инструмент mem_save и записывает заголовок, тип и поля что сделано, почему, где и что усвоено. Engram кладёт это в SQLite и строит индекс FTS5. В следующей сессии агент ищет по памяти через mem_search и получает нужный контекст обратно. Всего в наборе 19 MCP-инструментов, от сохранения и поиска до работы с сессиями и поиска конфликтов между записями. ▶️ Запуск Дальше подключаете агента одной командой. Для Claude Code это плагин. claude plugin marketplace add Gentleman-Programming/engram && claude plugin install engram Для других агентов есть готовые сетапы, например engram setup opencode или engram setup codex. Память можно смотреть и руками. Поиск из терминала выглядит так: engram search "авторизация по jwt" А для удобного просмотра есть TUI с навигацией по клавишам vim. engram tui ⚙️ Синхронизация между машинами Записи можно переносить через git. Engram экспортирует новые данные в сжатый чанк, вы коммитите его, а на другой машине импортируете: engram sync git add .engram/ && git commit -m "sync engram memories" engram sync --import Локальный SQLite остаётся главным источником правды. Облако подключается по желанию и нужно только для репликации и общего доступа. Агент перестаёт забывать контекст проекта и не заставляет вас объяснять одно и то же каждую сессию. Инструмент не привязан к конкретному агенту, ставится одним бинарником и хранит всё локально, поэтому попробовать его можно без облака и тяжёлых зависимостей. ➡️ Репозиторий Наша рассылка ничего не забывает 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
1 169
3
❓ Граница int Код простой: всего три строки. Но ответ знают не все. Подсказка: тип имеет значение. `int8` хранит числа в диап
❓ Граница int Код простой: всего три строки. Но ответ знают не все.   Подсказка: тип имеет значение. `int8` хранит числа в диапазоне от -128 до 127, и Go не остановит вас, если вы выйдете за пределы. ➡️ Ответ 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #ReadySetGo
1 579
4
🤔 Переживёт ли канал Timer.C вызовы Reset Частый вопрос про таймеры в Go. Вы создаёте time.Timer, сохраняете в отдельной переменной ссылку на канал Timer.C и хотите понять, остаётся ли этот канал тем же самым после вызова Reset. Если канал пересоздаётся, сохранённая ссылка станет бесполезной, а горутина будет ждать данные, которые никогда не придут. 🖇 Короткий ответ Канал Timer.C не пересоздаётся при вызове Reset. Вы можете хранить его отдельно, читать из него, ждать на нём, и он остаётся живым после любого числа вызовов Reset. Метод Reset меняет только момент срабатывания, сам канал он не трогает. Проверить это можно небольшой программой. Таймер срабатывает, мы печатаем прошедшее время, удваиваем задержку и снова запускаем тот же таймер: package main import ( "fmt" "time" ) func main() { start := time.Now() delay := time.Second t := time.NewTimer(delay) defer t.Stop() for range t.C { fmt.Println(time.Since(start)) delay *= 2 t.Reset(delay) if delay > 16*time.Second { return } } } Цикл for range t.C читает из одного и того же канала на каждой итерации. Если бы Reset подменял канал, цикл завис бы после первого срабатывания. Этого не происходит, программа печатает растущие интервалы, пока задержка не превысит шестнадцать секунд. Отдельно стоит вспомнить про изменение в Go 1.23. Раньше канал таймера имел буфер на один элемент, поэтому после Stop или Reset в нём мог остаться старый сигнал, и его приходилось вручную вычитывать. ❗️ С версии 1.23 канал стал небуферизованным, устаревшие значения больше в нём не задерживаются. Ещё таймеры и тикеры теперь освобождаются сборщиком мусора сразу, как только на них не осталось ссылок, даже без вызова Stop. Момент про сборку мусора в этом сценарии не важен. Программа держит ссылку и на сам таймер, и на его канал, поэтому ничего не освобождается раньше времени. Хранить Timer.C в отдельной переменной безопасно. Канал живёт столько же, сколько и сам таймер, а Reset влияет только на время срабатывания. Если вы пишете на Go 1.23 или новее, вручную чистить канал после Reset тоже не нужно, и это убирает старый источник ошибок. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
1 653
5
🔥 Строишь ИИ-агентов? Руководитель AI/ML-направления Сloud․ru покажет, где большинство архитектур ломаются, и как этого избе
🔥 Строишь ИИ-агентов? Руководитель AI/ML-направления Сloud․ru покажет, где большинство архитектур ломаются, и как этого избежать. 18 июня в 19:00 совместно с Сloud․ru проведём открытый урок «Мультиагентные системы: почему большинство архитектур переусложнены». Спикер — Дмитрий Юдин, эксперт по масштабированию и оптимизации вычислительных ресурсов для ML. Под его руководством развивается Evolution AI Factory — цифровая среда для работы с GenAI. Он занимается развитием сервисов генеративного ИИ, инфраструктуры для обучения больших языковых моделей и внедрением интеллектуальных агентов. Что получишь на уроке: — критерии выбора между одним агентом и мультиагентной системой; — разбор популярных архитектурных ошибок; — реальные ограничения современных ИИ-агентов; — практические рекомендации по проектированию агентных систем. 🎁 Для участников урока подготовили промокод на скидку 10 000 ₽. 🗓️ Когда: 18 июня, 19:00 (МСК) 👉 Занять место на открытом уроке
1 647
6
📹 Монтаж видео на Go без ручного ffmpeg MovieGo это библиотека на Go для монтажа видео. Под капотом она работает поверх паке
📹 Монтаж видео на Go без ручного ffmpeg MovieGo это библиотека на Go для монтажа видео. Под капотом она работает поверх пакета ffmpeg-go и даёт API с цепочками методов. Вы пишете обычный Go код, а команду для ffmpeg библиотека собирает сама.   Через неё можно нарезать ролик, склеить несколько в один, поменять размер, добавить плавное появление и затухание или снять кадр. Сам ffmpeg должен стоять в системе отдельно. Размер ResizeByWidth задаёт ширину, ResizeByHeight высоту, Resize сразу оба значения: first, _ := moviego.Load("forest.mp4") first.Resize(1000, 500).Output("resized.mp4").Run() Нарезка SubClip обрезает ролик по началу и концу отрезка в секундах. Тут кусок с третьей по пятую секунду: first.SubClip(3, 5).Output("final.mp4").Run() Склейка Concat собирает слайс Video в один ролик, прямо в слайсе можно применять эффекты к отдельным кускам: finalVideo, _ := moviego.Concat([]moviego.Video{ first, second.SubClip(5.3, 10.5), first.FadeIn(0, 5).FadeOut(5), }) finalVideo.Output("final.mp4").Run() Появление и затухание FadeIn и FadeOut работают с картинкой, AudioFadeIn и AudioFadeOut со звуком. Методы складываются в цепочку: first.FadeIn(0, 3).FadeOut(5).Output("fade.mp4").Run() first.FadeOut(5).AudioFadeOut(5).Output("fade-out.mp4").Run() Скриншот Screenshot сохраняет кадр по указанной секунде, в том числе после эффектов: first.Screenshot(5, "simple-screen.png") MovieGo снимает рутину по сборке команд ffmpeg руками и переводит монтаж на понятные методы. Подойдёт, чтобы автоматизировать обработку видео в Go сервисе, например генерировать превью или собирать ролики из частей. ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
1 856
7
👋 Привет, гоферы! Канал работает стабильно, без паник и утечек. Но мы нашли такую строку в коде: if boosts < needed { ret
👋 Привет, гоферы! Канал работает стабильно, без паник и утечек. Но мы нашли такую строку в коде: if boosts < needed { return fmt.Errorf("не хватает буста для крутых фич: %w", ErrSadAdmin) } Без бустов канал живёт, но с ними — раскрывает все горутины на полную. Один клик, и вы в списке тех, кто помог проекту. ➡️ Бустануть канал 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика
2 159
8
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
2 419
9
🔄 pgCenter 0.10.0, поддержка Postgres 15–18 и переход на pgx/v5 Вышел релиз v0.10.0 консольной утилиты pgcenter для наблюден
🔄 pgCenter 0.10.0, поддержка Postgres 15–18 и переход на pgx/v5 Вышел релиз v0.10.0 консольной утилиты pgcenter для наблюдения за Postgres. Это в основном обновление совместимости и безопасности, новых экранов в интерфейсе не добавили. Главное изменение это поддержка Postgres от 15 до 18. Запросы статистики обновили под формат версии 17, прогон тестов идёт на ветках с 14 по 18. Под капотом утилита перешла на драйвер pgx/v5, обновилась до Go 1.25.10 и закрыла накопившиеся уязвимости в зависимостях. Часть правок касается устойчивости и вывода: • Теперь pgcenter проверяет, включён ли pg_stat_statements в shared_preload_libraries, и больше не зависает, если расширение установлено в базе, но не активировано в конфигурации. • Длинные значения application_name из pg_stat_activity перестали обрезаться. • Адрес клиента в pg_stat_activity и pg_stat_replication теперь оборачивается в функцию host(), поэтому в выводе нет лишней маски подсети. Если вы уже пользуетесь pgcenter на свежих версиях Postgres, обновление снимает проблемы совместимости и убирает известные CVE. ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoLive
2 305
10
🥺 Big money вакансии для Go-разработчиков за неделю Middle / Senior Бэкенд разработчик — до 405 000 $ (в год) — удаленно по Сан-Франциско Golang-разработчик — до 400 000 ₽ в офис или удаленно (Москва) ➡️ Еще больше топовых вакансий — в нашем канале Go jobs 🐸 Библиотека Go-разработчика #GoWork
2 453
11
📎 Почему цепочка middleware ломает безопасность, даже когда каждый обработчик корректен Стек middleware разрастается до деся
📎 Почему цепочка middleware ломает безопасность, даже когда каждый обработчик корректен Стек middleware разрастается до десятка с лишним обработчиков. Каждый написан осознанно и протестирован, а ревью всё равно находит обход аутентификации. Дыра не внутри обработчика, а в порядке их выполнения. 👉 Почему так происходит Порядок обычно складывается стихийно. Обработчики добавляют по мере задач, и очерёдность повторяет хронологию, а не смысл. Кто добавлен раньше, тот снаружи. При этом влияние нового обработчика на безопасность всей цепочки никто не проверяет. В итоге порядок принимает решения, которые никто явно не принимал. Когда срабатывает аутентификация, может ли запрос получить ответ до неё, кто видит личность в контексте. Эта политика нигде не записана и меняется при каждой перестановке. 👉 Как этого избежать Разбейте цепочку на слои доверия и зафиксируйте, что внутри блока безопасности порядок обязателен: // Слой безопасности, порядок обязателен // авторизации нужна личность из контекста // аутентификации нужен резолв тенанта из контекста handler = authorizationMiddleware(handler) handler = authenticationMiddleware(handler) handler = tenantMiddleware(handler) Запретите ранний выход до аутентификации. Ни один обработчик выше блока безопасности не должен сам возвращать неошибочный ответ. Быстрый ответ на health check выносите на отдельный неаутентифицированный маршрут. Сделайте порядок проверяемым в CI. Пусть пайплайн отклоняет PR, который переставляет обработчики внутри блока безопасности без явного ревью. Тогда комментарии о порядке работают как ограничение, а не пожелание. Тестируйте цепочку целиком. Юнит тесты не ловят такие дыры, потому что баг живёт во взаимодействии. Нужны сквозные тесты на враждебные комбинации заголовков, путей и параметров. Полезнее спрашивать не про то, корректен ли каждый middleware, а про то, что цепочка считает истинным к моменту запуска каждого обработчика. Держите порядок явным, проверяемым и покрытым тестами на всю цепочку сразу. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
2 299
12
💻 top для Postgres прямо в терминале Postgres отдаёт массу статистики о своей работе. Активные сессии, запросы, репликация, блокировки, обращения к таблицам и индексам, прогресс вакуума. Всё это лежит в системных представлениях вроде pg_stat_activity и pg_stat_statements. Беда в том, что родного инструмента для удобной работы с этой статистикой у Postgres нет. Приходится держать в голове десятки запросов и руками дёргать представления через psql. Написанный на Go, pgCenter показывает статистику в живом интерфейсе, похожем на top. 🖇 Что он умеет Основная команда pgcenter top обновляет метрики в реальном времени и переключается между экранами по горячим клавишам. Видно сводку по базе, активность клиентов из pg_stat_activity, тяжёлые запросы из pg_stat_statements, состояние репликации, обращения к таблицам и индексам, прогресс операций вроде VACUUM, CREATE INDEX и COPY. Рядом идёт системная статистика, собранная из procfs. Это load average, загрузка CPU, память и swap, нагрузка на диски и сеть. Отдельно полезен экран по процессам, он открывается по Shift+S. Там pgcenter склеивает данные из pg_stat_activity с метриками каждого бэкенда из /proc/[pid]/stat и /proc/[pid]/io. Сразу видно, во что упёрся медленный запрос, в процессор или в диск, без выхода из утилиты. Экран работает только в локальном режиме. 🖇Как запустить Проще всего через Docker: docker pull lesovsky/pgcenter:latest docker run -it --rm lesovsky/pgcenter:latest pgcenter top -h 1.2.3.4 -U user -d dbname Если ставите пакетом, под DEB, RPM и APK есть готовые сборки на странице релизов. После установки запуск выглядит так: pgcenter top -h 127.0.0.1 -U postgres -d mydb Кроме живого режима есть запись статистики на будущее. Команда pgcenter record складывает метрики в файлы, а pgcenter report строит из них отчёты для разбора уже после инцидента. Метрики по процессам тоже пишутся, и их можно проиграть через pgcenter report -N. Ещё внутри есть профайлер событий ожидания, просмотр и правка конфигов с перезагрузкой сервиса, а также чтение логов Postgres без остановки мониторинга. 🖇 Пара ограничений Утилита рассчитана на Linux и на других системах работать не будет. Для полного доступа к статистике нужны права SUPERUSER либо роли для чтения метрик и логов. С удалённым Postgres и с Amazon RDS часть функций недоступна, потому что туда не попадает системная статистика хоста. ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
2 194
13
🔥 Приглашаем на бесплатный открытый вебинар курса «Высоконагруженные системы: архитектура и масштабирование»: «Асинхронная о
🔥 Приглашаем на бесплатный открытый вебинар курса «Высоконагруженные системы: архитектура и масштабирование»: «Асинхронная обработка данных в высоконагруженных системах» 🗓 Когда: 16 июня, 20:00 (мск) На вебинаре разберём, как грамотно внедрять асинхронность и строить по-настоящему производительные системы. Что будет на вебинаре: — Зачем и когда переходить на асинхронную обработку данных в высоконагруженных проектах — Очереди сообщений, веб-сокеты и другие инструменты асинхронного взаимодействия — Реальный архитектурный кейс: от веб-сервера до брокера сообщений и базы данных — Типичные узкие места асинхронных систем и проверенные способы их устранения 👉 Зарегистрироваться: https://otus.ru/lessons/highloadarchitect/?utm_source=telegram&utm_medium=cpm&utm_campaign=hl&utm_term=goproglib&utm_content=mql-lesson-16-06-2026_test_usp-universal_hl_text_no-headline_text_long_aibanner_lesson-banner_white_standart#event-7191 Бесплатное занятие приурочено к курсу «Высоконагруженные системы: архитектура и масштабирование», где вы научитесь проектировать высоконагруженные системы, способные выдерживать экстремальные нагрузки и работать стабильно в любых условиях. 🎁При покупке курса вы получите в подарок мини-курс по Kafka, который поможет подготовиться к собеседованию в бигтех Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576
2 150
14
🧑‍💻 Зачем мьютекс в uuid, если UUID не хранят состояние В исходниках пакета uuid рядом с генерацией UUIDv7 лежит мьютекс ур
🧑‍💻 Зачем мьютекс в uuid, если UUID не хранят состояние В исходниках пакета uuid рядом с генерацией UUIDv7 лежит мьютекс уровня пакета и переменная с временем последнего вызова. UUID считаются значениями без состояния, поэтому блокировка выглядит лишней. Разберём, зачем она там. Первые 48 бит UUIDv7 это метка времени в миллисекундах. Поэтому такие значения сортируются по времени создания и удобны как ключи в базе. Но внутри одной миллисекунды программа создаёт тысячи идентификаторов с одинаковой меткой, и без счётчика их порядок стал бы случайным. Пакет хранит последнее выданное время вместе со счётчиком в lastV7time и проверяет, что новое значение строго больше прошлого: func getV7Time() (milli, seq int64) { timeMu.Lock() defer timeMu.Unlock() nano := timeNow().UnixNano() milli = nano / nanoPerMilli seq = (nano - milli*nanoPerMilli) >> 8 now := milli<<12 + seq if now <= lastV7time { now = lastV7time + 1 milli = now >> 12 seq = now & 0xfff } lastV7time = now return milli, seq } Если посчитанное время не больше прошлого, функция берёт lastV7time + 1. Так порядок держится даже при переводе часов назад, просто встроенная метка ненадолго разойдётся с реальной. Мьютекс нужен потому, что NewV7 зовут из разных горутин, а lastV7time одна на весь пакет. Используется общий timeMu, тот же, что защищает время старых версий UUID. Состояние живёт в одном процессе. Между несколькими машинами строгий порядок внутри миллисекунды не гарантирован, хотя сортировка по времени всё равно работает. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
2 178
15
🌴 Деревья поиска на Go: вставка, поиск, удаление BST — двоичное дерево поиска. Простая идея: левый потомок всегда меньше родителя, правый — больше. Это даёт поиск за O(log n), но только если дерево сбалансировано. Об этом — в конце поста. Структура узла type Node struct { Val int Left *Node Right *Node } type BST struct { Root *Node } Вставка Идём по дереву вниз: если значение меньше текущего узла — налево, больше — направо. Когда упёрлись в nil — вставляем: func (t *BST) Insert(val int) { t.Root = insert(t.Root, val) } func insert(node *Node, val int) *Node { if node == nil { return &Node{Val: val} } if val < node.Val { node.Left = insert(node.Left, val) } else if val > node.Val { node.Right = insert(node.Right, val) } return node } Дубликаты здесь просто игнорируются. Можно добавить счётчик в узел, если нужно их хранить. Поиск Та же логика, что и вставка, но вместо создания узла возвращаем результат: func (t *BST) Search(val int) bool { return search(t.Root, val) } func search(node *Node, val int) bool { if node == nil { return false } if val == node.Val { return true } if val < node.Val { return search(node.Left, val) } return search(node.Right, val) } Удаление Три случая: - узел без потомков — просто удаляем - узел с одним потомком — заменяем им - узел с двумя потомками — находим минимальный элемент правого поддерева (in-order successor), ставим его на место удалённого func (t *BST) Delete(val int) { t.Root = deleteNode(t.Root, val) } func deleteNode(node *Node, val int) *Node { if node == nil { return nil } if val < node.Val { node.Left = deleteNode(node.Left, val) } else if val > node.Val { node.Right = deleteNode(node.Right, val) } else { if node.Left == nil { return node.Right } if node.Right == nil { return node.Left } // Находим минимум в правом поддереве min := findMin(node.Right) node.Val = min.Val node.Right = deleteNode(node.Right, min.Val) } return node } func findMin(node *Node) *Node { for node.Left != nil { node = node.Left } return node } Обходы Три классических варианта, каждый даёт узлы в разном порядке: // In-order: левый → корень → правый (отдаёт отсортированный список) func inOrder(node *Node) { if node == nil { return } inOrder(node.Left) fmt.Println(node.Val) inOrder(node.Right) } // Pre-order: корень → левый → правый (удобен для копирования дерева) func preOrder(node *Node) { if node == nil { return } fmt.Println(node.Val) preOrder(node.Left) preOrder(node.Right) } // Post-order: левый → правый → корень (удобен для удаления дерева) func postOrder(node *Node) { if node == nil { return } postOrder(node.Left) postOrder(node.Right) fmt.Println(node.Val) } Где ломается BST Если вставлять элементы по порядку — 1, 2, 3, 4, 5 — дерево вырождается в связный список. Поиск становится O(n) вместо O(log n): 1 \ 2 \ 3 \ 4 \ 5 Именно для этого придумали самобалансирующиеся деревья. 💬 Разбирать механизм, который не даёт дереву деградировать? 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #ReadySetGo
2 159
16
🗑 Сборщик мусора видно прямо в терминале Растут задержки в Go-сервисе? Обычно включают GODEBUG=gctrace=1 и втыкают в простыню логов в stderr. Поймать там всплеск STW-паузы или понять, что GC стал срабатывать чаще после правок, почти нереально. gcscope рисует это вживую. Терминальный TUI показывает GC-циклы, STW-паузы, рост кучи (live/goal) и сигналы pacer в реальном времени. Попробовать демо Встроенная демо-нагрузка, ничего ставить не надо. go run ./cmd/gcscope lab churn ➡️ На своём коде Собираем бинарник и запускаем под наблюдением. go build -o ./myapp ./cmd/myapp gcscope run ./myapp -- --your-flag value Код приложения менять не нужно. Всё после -- уходит в вашу программу. ➡️ Что ещё умеет Режим attach цепляется к живому сервису по HTTP через runtime/metrics. Режим diff сравнивает два snapshot-файла и показывает разницу по heap и STW между запусками. Историю можно листать на паузе, графики зумить, состояние сохранять в JSON клавишей s. Ставится одной командой: go install github.com/timur-developer/gcscope/cmd/gcscope@latest ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
2 505
17
✏️ Переменная цикла своя на каждой итерации В Go переменная цикла for ... range создаётся заново на каждой итерации. Это снимает одну из самых частых проблем при работе с горутинами и замыканиями, когда несколько функций случайно ссылаются на одно и то же значение. Разберём как этим пользоваться. Замыкание захватывает не значение переменной, а саму переменную. Если бы v была одна на весь цикл, все запущенные горутины ссылались бы на общую ячейку и видели бы её последнее значение. Поскольку в Go у каждой итерации своя v, такого не происходит: for _, v := range data { go func() { fmt.Println(v) }() } Каждая горутина печатает значение своей итерации, а не последний элемент data. Никаких обходных приёмов внутри тела цикла для этого не нужно. На каждом проходе компилятор заводит новую переменную и копирует в неё текущее значение. Замыкание, которое вы создаёте внутри тела, привязывается именно к этой копии. Когда итерация заканчивается, её переменная остаётся жить ровно столько, сколько на неё ссылаются запущенные функции. То же касается и индекса в форме с двумя переменными: for i, v := range items { go func() { fmt.Println(i, v) }() } И i, и v уникальны для каждого прохода, поэтому пара значений всегда соответствует своей итерации. Поведение привязано к версии языка в директиве go файла go.mod. Оно действует, когда там указано go 1.22 или выше. Если в модуле прописана версия старше, тот же код соберётся со старой семантикой даже на новом компиляторе. Так одна и та же кодовая база ведёт себя предсказуемо, а апгрейд тулчейна не меняет логику молча. ℹ️ О чём помнить Копия создаётся под каждую итерацию, но это именно копия значения. Если в v лежит срез или указатель, копируется он, а не данные за ним, и общий доступ к этим данным из горутин по-прежнему требует синхронизации. Свойство решает проблему захвата переменной, а не гонок по самим данным. Опираться на это можно в любом коде, где замыкания и горутины создаются внутри for ... range. Значение каждой итерации остаётся при ней, и писать переобъявление внутри тела больше не требуется. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
2 581
18
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
2 625
19
🔥 Инженерная методичка по ИИ от Романа Барлоса (Team Lead в Yandex Cloud) Продолжаем делиться экспертизой команды курса «Раз
🔥 Инженерная методичка по ИИ от Романа Барлоса (Team Lead в Yandex Cloud) Продолжаем делиться экспертизой команды курса «Разработка ИИ-агентов». Роман собрал мастхев-инструменты и ключевые работы для тех, кто хочет выйти за рамки вайбкодинга. 🛠️ Полезные инструменты: • Understand Anything — граф знаний по коду и зависимостям. • DeepTutor — open-source платформа для персонализированного обучения. • Superpowers — набор практик для системной разработки с ИИ. • Awesome Agent Skills — коллекция навыков для ИИ-агентов. 📚 Ключевые работы по LLM: • Attention Is All You Need (2017) — архитектура Transformer. • GPT-1 (2018) — начало эпохи GPT. • GPT-2 (2019) — решение новых задач без дообучения. • GPT-3 (2020) — обучение на примерах из запроса. • InstructGPT (2022) — RLHF и современные чат-боты. На курсе Роман выступает консультантом программы: помогает формировать содержание уроков с опорой на актуальные инженерные практики». Занять свое место на потоке: 👉 Курс «Разработка ИИ-агентов»
2 495
20
🤩 Разбор строк через strings.Cut Часто строку нужно разрезать ровно один раз по разделителю. Так делят почту на имя и домен, заголовок на ключ и значение, путь на префикс и остаток. Раньше для этого брали strings.Index или strings.Split, и оба варианта тянули за собой лишний код с проверкой границ. В Go 1.18 появился strings.Cut, который закрывает этот случай одной строкой. strings.Index возвращает позицию разделителя или -1, если его нет. Дальше нужно вручную проверять результат и аккуратно нарезать строку по смещениям, не выходя за границы. Старый способ: i := strings.Index(email, "@") if i < 0 { return "", "", false } username := email[:i] domain := email[i+1:] Три строки на нарезку плюс отдельная проверка на -1. Если забыть про +1, в домен попадёт сам символ разделителя. Современный способ: username, domain, found := strings.Cut(email, "@") Функция возвращает часть до разделителя, часть после него и флаг found. Если разделителя нет, found будет false, а первой частью вернётся вся исходная строка. Чем отличается от `strings.Split` strings.Split режет строку по всем вхождениям и возвращает срез. Когда разрез нужен один, приходится брать SplitN с лимитом и потом разбирать срез по индексам. strings.Cut сразу отдаёт две именованные части и не выделяет срез под результат, поэтому работает экономнее. Практический пример Разбор строки заголовка вида Content-Type: application/json выглядит так: key, value, ok := strings.Cut(header, ": ") if !ok { return fmt.Errorf("invalid header: %q", header) } key = strings.TrimSpace(key) value = strings.TrimSpace(value) Флаг ok сразу отделяет корректные строки от мусора, без ручной возни с индексами. Используйте strings.Cut везде, где строку нужно разделить ровно один раз, а Split оставьте для случаев с множеством вхождений. Код станет короче, а ошибок с границами среза не будет. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
2 471