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

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

Відкрити в Telegram

Все самое полезное для Go-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/32d20779 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0 #WXSSA

Показати більше

📈 Аналітичний огляд Telegram-каналу Библиотека Go-разработчика | Golang

Канал Библиотека Go-разработчика | Golang (@goproglib) у мовному сегменті Російська є активним учасником. На даний момент спільнота об'єднує 24 004 підписників, посідаючи 5 688 місце в категорії Технології та додатки та 27 925 місце у регіоні Росія.

📊 Показники аудиторії та динаміка

З моменту свого створення невідомо, проект продемонстрував стрімке зростання, зібравши аудиторію у 24 004 підписників.

За останніми даними від 09 червня, 2026, канал демонструє стабільну активність. Хоча за останні 30 днів спостерігається зміна кількості учасників на 54, а за останні 24 години на 1, загальне охоплення залишається високим.

  • Статус верифікації: Не верифікований
  • Рівень залученості (ER): Середній показник залученості аудиторії становить 10.58%. Протягом перших 24 годин після публікації контент зазвичай збирає 7.65% реакцій від загальної кількості підписників.
  • Охоплення публікацій: В середньому кожен допис отримує 2 539 переглядів. Протягом першої доби публікація в середньому набирає 1 837 переглядів.
  • Реакції та взаємодія: Аудиторія активно підтримує контент: середня кількість реакцій на один пост – 8.
  • Тематичні інтереси: Контент зосереджений навколо ключових тем, таких як навигация, лучшее_из_библиотеки_2025, git, string, golive.

📝 Опис та контентна політика

Автор описує ресурс як майданчик для висловлення суб'єктивної думки:
Все самое полезное для Go-разработчика в одном канале. По рекламе: @proglib_adv Учиться у нас: https://proglib.io/w/32d20779 Для обратной связи: @proglibrary_feeedback_bot РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0 #WXSSA

Завдяки високій частоті оновлень (останні дані отримано 10 червня, 2026), канал підтримує актуальність та високий рівень охоплення публікацій. Аналітика показує, що аудиторія активно взаємодіє з контентом, що робить його важливою точкою впливу в категорії Технології та додатки.

24 004
Підписники
+124 години
-177 днів
+5430 день
Залучення підписників
червень '26
червень '26
+55
в 2 каналах
травень '26
+288
в 3 каналах
Get PRO
квітень '26
+249
в 1 каналах
Get PRO
березень '26
+216
в 1 каналах
Get PRO
лютий '26
+487
в 7 каналах
Get PRO
січень '26
+346
в 3 каналах
Get PRO
грудень '25
+370
в 4 каналах
Get PRO
листопад '25
+384
в 4 каналах
Get PRO
жовтень '25
+331
в 2 каналах
Get PRO
вересень '25
+290
в 0 каналах
Get PRO
серпень '25
+316
в 4 каналах
Get PRO
липень '25
+317
в 2 каналах
Get PRO
червень '25
+315
в 0 каналах
Get PRO
травень '25
+391
в 5 каналах
Get PRO
квітень '25
+358
в 4 каналах
Get PRO
березень '25
+625
в 53 каналах
Get PRO
лютий '25
+527
в 35 каналах
Get PRO
січень '25
+517
в 37 каналах
Get PRO
грудень '24
+591
в 40 каналах
Get PRO
листопад '24
+605
в 52 каналах
Get PRO
жовтень '24
+499
в 36 каналах
Get PRO
вересень '24
+676
в 36 каналах
Get PRO
серпень '24
+580
в 36 каналах
Get PRO
липень '24
+586
в 37 каналах
Get PRO
червень '24
+467
в 29 каналах
Get PRO
травень '24
+674
в 35 каналах
Get PRO
квітень '24
+771
в 36 каналах
Get PRO
березень '24
+901
в 31 каналах
Get PRO
лютий '24
+729
в 31 каналах
Get PRO
січень '24
+863
в 27 каналах
Get PRO
грудень '23
+850
в 29 каналах
Get PRO
листопад '23
+608
в 10 каналах
Get PRO
жовтень '23
+697
в 25 каналах
Get PRO
вересень '23
+723
в 0 каналах
Get PRO
серпень '23
+648
в 0 каналах
Get PRO
липень '23
+503
в 0 каналах
Get PRO
червень '23
+422
в 0 каналах
Get PRO
травень '23
+568
в 0 каналах
Get PRO
квітень '23
+365
в 0 каналах
Get PRO
березень '23
+841
в 0 каналах
Get PRO
лютий '23
+392
в 0 каналах
Get PRO
січень '23
+395
в 0 каналах
Get PRO
грудень '22
+384
в 0 каналах
Get PRO
листопад '22
+491
в 0 каналах
Get PRO
жовтень '22
+256
в 0 каналах
Get PRO
вересень '22
+292
в 0 каналах
Get PRO
серпень '22
+394
в 0 каналах
Get PRO
липень '22
+472
в 0 каналах
Get PRO
червень '22
+443
в 0 каналах
Get PRO
травень '22
+176
в 0 каналах
Get PRO
квітень '22
+328
в 0 каналах
Get PRO
березень '22
+242
в 0 каналах
Get PRO
лютий '22
+135
в 0 каналах
Get PRO
січень '22
+236
в 0 каналах
Get PRO
грудень '21
+245
в 0 каналах
Get PRO
листопад '21
+219
в 0 каналах
Get PRO
жовтень '21
+215
в 0 каналах
Get PRO
вересень '21
+290
в 0 каналах
Get PRO
серпень '21
+298
в 0 каналах
Get PRO
липень '21
+281
в 0 каналах
Get PRO
червень '21
+196
в 0 каналах
Get PRO
травень '21
+389
в 0 каналах
Get PRO
квітень '21
+336
в 0 каналах
Get PRO
березень '21
+280
в 0 каналах
Get PRO
лютий '21
+258
в 0 каналах
Get PRO
січень '21
+262
в 0 каналах
Get PRO
грудень '20
+6 566
в 0 каналах
Дата
Залучення підписників
Згадування
Канали
10 червня+3
09 червня+8
08 червня+1
07 червня+7
06 червня+2
05 червня+10
04 червня+4
03 червня+7
02 червня+8
01 червня+5
Дописи каналу
🔄 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
🥺 Big money вакансии для Go-разработчиков за неделю Middle / Senior Бэкенд разработчик — до 405 000 $ (в год) — удаленно по Сан-Франциско Golang-разработчик — до 400 000 ₽ в офис или удаленно (Москва) ➡️ Еще больше топовых вакансий — в нашем канале Go jobs 🐸 Библиотека Go-разработчика #GoWork
1 778
3
📎 Почему цепочка middleware ломает безопасность, даже когда каждый обработчик корректен Стек middleware разрастается до деся
📎 Почему цепочка middleware ломает безопасность, даже когда каждый обработчик корректен Стек middleware разрастается до десятка с лишним обработчиков. Каждый написан осознанно и протестирован, а ревью всё равно находит обход аутентификации. Дыра не внутри обработчика, а в порядке их выполнения. 👉 Почему так происходит Порядок обычно складывается стихийно. Обработчики добавляют по мере задач, и очерёдность повторяет хронологию, а не смысл. Кто добавлен раньше, тот снаружи. При этом влияние нового обработчика на безопасность всей цепочки никто не проверяет. В итоге порядок принимает решения, которые никто явно не принимал. Когда срабатывает аутентификация, может ли запрос получить ответ до неё, кто видит личность в контексте. Эта политика нигде не записана и меняется при каждой перестановке. 👉 Как этого избежать Разбейте цепочку на слои доверия и зафиксируйте, что внутри блока безопасности порядок обязателен: // Слой безопасности, порядок обязателен // авторизации нужна личность из контекста // аутентификации нужен резолв тенанта из контекста handler = authorizationMiddleware(handler) handler = authenticationMiddleware(handler) handler = tenantMiddleware(handler) Запретите ранний выход до аутентификации. Ни один обработчик выше блока безопасности не должен сам возвращать неошибочный ответ. Быстрый ответ на health check выносите на отдельный неаутентифицированный маршрут. Сделайте порядок проверяемым в CI. Пусть пайплайн отклоняет PR, который переставляет обработчики внутри блока безопасности без явного ревью. Тогда комментарии о порядке работают как ограничение, а не пожелание. Тестируйте цепочку целиком. Юнит тесты не ловят такие дыры, потому что баг живёт во взаимодействии. Нужны сквозные тесты на враждебные комбинации заголовков, путей и параметров. Полезнее спрашивать не про то, корректен ли каждый middleware, а про то, что цепочка считает истинным к моменту запуска каждого обработчика. Держите порядок явным, проверяемым и покрытым тестами на всю цепочку сразу. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
1 873
4
💻 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
1 968
5
🔥 Приглашаем на бесплатный открытый вебинар курса «Высоконагруженные системы: архитектура и масштабирование»: «Асинхронная о
🔥 Приглашаем на бесплатный открытый вебинар курса «Высоконагруженные системы: архитектура и масштабирование»: «Асинхронная обработка данных в высоконагруженных системах» 🗓 Когда: 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
1 845
6
🧑‍💻 Зачем мьютекс в 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
1 838
7
🌴 Деревья поиска на 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
1 822
8
🗑 Сборщик мусора видно прямо в терминале Растут задержки в 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 226
9
✏️ Переменная цикла своя на каждой итерации В 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 162
10
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
2 233
11
🔥 Инженерная методичка по ИИ от Романа Барлоса (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 182
12
🤩 Разбор строк через 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 115
13
📰 Первый летний дайджест Короткий, как и отпуск.. — Go закрыл три уязвимости Вышли версии Go 1.26.4 и 1.25.11. Закрывают три
📰 Первый летний дайджест Короткий, как и отпуск.. — Go закрыл три уязвимости Вышли версии Go 1.26.4 и 1.25.11. Закрывают три уязвимости в стандартной библиотеке. — Go может разрешить превращать функции в интерфейсы с одним методом В трекере Go обсуждают предложение #47487. Оно разрешает приводить значение функции к интерфейсу с ровно одним методом, если сигнатура функции совпадает с сигнатурой этого метода. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoLive
2 174
14
🧑‍💻 Конструктор, из которого собран Docker Когда вы запускаете контейнер, под капотом работает движок. Писать такой движок
🧑‍💻 Конструктор, из которого собран Docker Когда вы запускаете контейнер, под капотом работает движок. Писать такой движок с нуля никто не хочет, там слишком много низкоуровневой возни с неймспейсами, cgroups, образами и сетью. Moby — это открытый проект, который Docker вынес в апстрим, набор готовых компонентов для сборки систем на контейнерах. Из этих кубиков собран сам Docker, и из них же вы можете собрать что-то своё. ➡️ Что внутри. Moby это не одна программа, а коллекция компонентов с понятными API, среди них движок выполнения контейнеров, инструменты сборки образов, работа с реестром и оркестрация. Идея в том, чтобы каждый кусок имел чёткую функцию и при желании заменялся на другой. ➡️ Как с ним работать. Чаще всего вы общаетесь с движком через Docker CLI, но из Go можно дёргать тот же Engine API напрямую. Вот аналог docker ps, который читает настройки из переменных окружения вроде DOCKER_HOST и сам согласует версию API с демоном: package main import ( "context" "fmt" "log" "github.com/moby/moby/client" ) func main() { apiClient, err := client.New(client.FromEnv) if err != nil { log.Fatal(err) } defer apiClient.Close() result, err := apiClient.ContainerList(context.Background(), client.ContainerListOptions{ All: true, }) if err != nil { log.Fatal(err) } for _, ctr := range result.Items { fmt.Printf("%s %s %s\n", ctr.ID, ctr.Status, ctr.Image) } } Этого хватает, чтобы из своего сервиса запускать контейнеры, тянуть образы, читать логи и управлять сетью, то есть делать всё то же, что умеет команда docker. ➡️ Кому это нужно. Moby рассчитан на инженеров и энтузиастов, которым интересно ковыряться в открытом коде, чинить баги и строить системы на контейнерах. Если коротко, Moby это фундамент Docker, открытый и модульный. Брать его стоит тогда, когда вам мало готового движка и хочется собрать или допилить свой. ➡️ Репозиторий 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
2 231
15
Попросил нейронку написать счётчик сотрудников.. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разр
Попросил нейронку написать счётчик сотрудников.. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoGiggle
2 499
16
📎 Чего не дают логи, метрики и трейсы Идея «три столпа наблюдаемости» звучит убедительно. Соберите логи, метрики и трейсы, отправьте в одну платформу, и поймёте систему. На практике у команды есть все три, а баг в проде она всё равно не находит. Ниже главные мысли статьи о том, почему так выходит, с примерами на Go. 🖇 Данные есть, понимания нет Три столпа дают сигналы, но не объяснение. На инциденте вы коррелируете то, что собрали заранее, часто в спешке, и этого набора не хватает под конкретный сбой. 🖇 Высокая кардинальность бьёт первой Как только вам нужен разрез по user_id, арендатору или связке эндпоинт плюс регион, метрики ломаются. Так делать не стоит, потому что число рядов взрывается: // Плохо. user_id и tenant дают почти неограниченное число комбинаций. httpRequests := prometheus.NewCounterVec( prometheus.CounterOpts{Name: "http_requests_total"}, []string{"endpoint", "region", "user_id", "tenant"}, ) httpRequests.WithLabelValues(endpoint, region, userID, tenant).Inc() Безопаснее держать в метках только ограниченный набор значений, а детали уносить в трейс или лог: // Лучше. В метках только то, у чего мало возможных значений. httpRequests := prometheus.NewCounterVec( prometheus.CounterOpts{Name: "http_requests_total"}, []string{"endpoint", "region", "status"}, ) httpRequests.WithLabelValues(endpoint, region, status).Inc() 🖇 Инструментация видит только ожидаемое Вы измеряете то, что предусмотрели заранее. Новый тип сбоя не попадает ни в один график, и в этот момент вы слепы. 🖇 Худшие баги живут между сервисами Два микросервиса по своим метрикам здоровы, задержки в трейсах нормальные, логи чистые. А вместе они выдают неверный ответ. Проблема в связи между ними, и ни одна отдельная метрика её не ловит. 🖇 Зелёные метрики не значат правильный результат Три столпа описывают инфраструктуру, а не бизнес. Сервис может держать отличную задержку и нулевые ошибки, при этом считать цену неверно. Поэтому полезно мерить сам бизнес-результат, а не только технику: // Считаем не задержку, а расхождение цены. Это и есть семантическая наблюдаемость. span.SetAttributes( attribute.String("order.id", order.ID), attribute.Int64("order.expected_cents", expected), attribute.Int64("order.charged_cents", charged), ) if charged != expected { priceMismatchTotal.Inc() } 🖇 Лучшее улучшение делается после инцидента Самый сильный приём звучит скучно. После разбора спросите, какой информации не хватило, и добавьте её. Часто это пара полей в структурном логе через slog, которых раньше не было: // После разбора добавили request_id и tenant. Без них инцидент искали вслепую. slog.Error("payment declined", "request_id", reqID, "tenant", tenant, "provider", provider, "code", declineCode, ) Эффект накапливается, и через год полтора команда отлаживает прод заметно быстрее. Вывод простой. Три столпа это стартовая точка, а не финал. Современные системы грязнее и сильнее завязаны на деньги, поэтому и наблюдаемость нужна с высокой кардинальностью, ориентированная на события и привязанная к бизнес-результату. Наша рассылка даёт максимум за минимум. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoDeep
2 231
17
😎 Знакомьтесь с экспертом Proglib.academy: Senior Software Engineer и Team Lead в Yandex Cloud Роман Барлос Роман — консульт
😎 Знакомьтесь с экспертом Proglib.academy: Senior Software Engineer и Team Lead в Yandex Cloud Роман Барлос Роман — консультант нашего курса «Разработка ИИ-агентов». Он работает на стыке cloud-native архитектуры и AI, активно внедряя современные ИИ-подходы в реальные процессы разработки. За что его ценит IT-комьюнити? 🟣 Team Lead и AI-евангелист в команде UX Yandex Cloud 14-лет в разработке. Занимается AI-адопшеном в команде Yandex Cloud, проводит мастер-классы и продвигает лучшие практики для повышения эффективности разработчиков. 🟣 Техлид Sourcecraft Code Assistant С сильным практическим бэкграундом принимал участие как технический лид в создании мощного AI-расширения для VS Code. 🟣 Создатель полезного Open Source Разрабатывает утилиты, которые позволяют быстро начать эксперименты с инференсом и агентами в локальном окружении: например, набор скриптов vllm-setup для быстрого запуска окружения и mini-proxy — минималистичный прокси для OpenAI API провайдеров. 🟣 Автор интерактивных ML-визуализаций Объясняет сложные концепции наглядно. Создал серию залипательных обучающих материалов, где можно вживую пощупать работу сетей Хопфилда, машин Больцмана и VC-размерности. Роман регулярно делится инженерными наработками, инсайтами и экспертизой в своем авторском Telegram-канале На курсе Роман выступает консультантом программы: он помогает формировать содержание уроков с опорой на актуальные инженерные практики и жесткие требования индустрии. Узнать больше о программе и разработке автономных систем: 👉 Курс «Разработка ИИ-агентов» Так, продолжаем знакомить вас с командой? 👍 — Да, ждем новых лиц 🔥 — Жду полезные материалы от Романа
2 261
18
❓ Можно ли использовать слайс как ключ в мапе Вопрос на первый взгляд простой, но именно такие мелочи отделяют тех, кто Go использует, от тех, кто Go понимает. Прежде чем лезть в документацию — подумайте сами. Вот что стоит вспомнить: 🔹 В Go ключ мапы должен быть comparable — то есть поддерживать операции == и != 🔹 Спросите себя: можно ли сравнить два слайса через ==? Что вообще значит «два слайса равны»? ➡️ Ответ 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #ReadySetGo
2 504
19
📎 Обёртывание ошибок через %w В Go 1.13 появился %w, который сохраняет исходную ошибку внутри обёртки и позволяет проверять её дальше по коду через errors.Is и errors.As. Когда ошибка проходит через несколько слоёв приложения, на каждом уровне к ней добавляют контекст. Если при этом теряется исходный тип, наверху остаётся только текст, и проверить причину можно лишь по подстроке. Любая правка формулировки ломает такую проверку. Старый способ: fmt.Errorf("failed to fetch user: %v", err) %v подставляет текст ошибки и выбрасывает сам объект. Узнать, что под капотом лежала sql.ErrNoRows, после этого уже нельзя. Современный способ: fmt.Errorf("failed to fetch user: %w", err) %w оборачивает ошибку и сохраняет ссылку на оригинал, поэтому цепочку потом можно размотать. Как проверять причину errors.Is идёт по всей цепочке обёрток и сравнивает каждое звено с конкретным значением: if errors.Is(err, sql.ErrNoRows) { // пользователь не найден } Не важно, сколько слоёв обёрток сверху, проверка доберётся до нужной ошибки. Когда нужен сам объект Если требуется не просто факт совпадения, а доступ к полям ошибки, помогает errors.As. Он находит в цепочке ошибку нужного типа и записывает её в переменную: var pathErr *os.PathError if errors.As(err, &pathErr) { slog.Error("ошибка пути", "path", pathErr.Path) } Своя ошибка в цепочке Чтобы ваш тип распознавался через errors.Is и errors.As, достаточно реализовать метод Unwrap: type AppError struct { Code int Err error } func (e *AppError) Unwrap() error { return e.Err } %w заменил хрупкое сравнение строк на надёжную проверку по значению и по типу. Оборачивайте ошибки этим глаголом везде, где добавляете контекст, и используйте errors.Is вместо сравнения текста. 📍 Навигация: Вакансии • Задачи • Собесы • Канал в Max 🐸 Библиотека Go-разработчика #GoToProduction
2 640
20
🫳 Типичная микросервисная архитектура 🫳 Постоянно слышу, что монолит - это прошлое, а микросервисы, типа единственный путь
🫳 Типичная микросервисная архитектура 🫳 Постоянно слышу, что монолит - это прошлое, а микросервисы, типа единственный путь к успеху. Все ищут ту самую структуру, которая позволит масштабироваться до бесконечности. На схеме классический скелет современной системы. Выглядит разумно, но без четкого понимания каждый блок может стать точкой отказа: • API Gateway Единая точка входа для всех клиентов. Итог: если гейтвей "прилег" или перегружен, твои крутые микросервисы внизу превращаются в бесполезный набор кода, до которого никто не может достучаться. • Load Balancer Раскидывает трафик, чтобы один сервер не закипел. Итог: всё работает плавно, пока балансировщик правильно настроен. Ошибка в конфиге и весь трафик летит в один сервис, убивая его за секунды. • Service Registry & Discovery Сервисы должны как-то находить друг друга. Итог: если эта штука заглючит, сервис А просто не узнает, где искать сервис Б. Система развалится на куски, которые не умеют общаться. • Разделение по доменам (Domain A / Domain B) У каждого сервиса своя база. Итог: ты получаешь независимость, но платишь за это адом при попытке собрать общую аналитику или сделать сложный транзакционный запрос между доменами. Уже переезжали на микросервисы? ❤️ — да, это было больно, но оно того стоило 🔥 — сидим на монолите и в ус не дуем 🔹 Практический интенсив «Архитектуры и шаблоны проектирования» 🔹 Получить консультацию менеджера 🔹 Сайт Академии 🔹 Сайт Proglib 🏃‍♀️ Азбука айтишника #ликбез
2 534