作者将该频道定位为表达主观观点的平台: “Все самое полезное для Go-разработчика в одном канале.
Учиться у нас: clc.to/qaSdww
По рекламе: @proglib_adv
Для обратной связи: @proglibrary_feeedback_bot
РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0
#WXSSA”
\n`))\n\nСтрока javascript:alert(1) в href превратится в #ZgotmplZ, то есть ссылка просто не сработает.\n\n➡️ Где защита отключается\n\nТипы template.HTML, template.JS, template.URL говорят шаблонизатору доверять содержимому и не трогать его. Это законная возможность, но применять её к данным пользователя нельзя:\n// так делать нельзя\ndata.Bio = template.HTML(userInput)\n\nЕсли пользователю действительно нужен HTML, например разметка в комментариях, содержимое надо чистить санитайзером:\nimport \"github.com/microcosm-cc/bluemonday\"\n\np := bluemonday.UGCPolicy()\nsafe := template.HTML(p.Sanitize(userInput))\n\nbluemonday работает по белому списку тегов и атрибутов, всё остальное вырезает.\n\n➡️ API и заголовки\n\nДля JSON ответов достаточно encoding/json, он экранирует <, > и & в escape последовательности. Но заголовок ставить обязательно, иначе браузер может угадать тип и отрендерить ответ как HTML.\nw.Header().Set(\"Content-Type\", \"application/json; charset=utf-8\")\nw.Header().Set(\"X-Content-Type-Options\", \"nosniff\")\njson.NewEncoder(w).Encode(resp)\n\nХорошая практика добавить Content-Security-Policy, который запрещает инлайновые скрипты. Он не заменяет экранирование, но снижает шанс, что случайная дыра превратится в кражу сессий. Куки сессии стоит помечать HttpOnly, тогда украденный скрипт до них не доберётся.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoDeep","datePublished":"2026-07-16T07:02:01Z","dateModified":"2026-07-16T07:02:01Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2419},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":11},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":32}]}},{"@type":"ListItem","position":3,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7407","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7407","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7407","headline":"🧑💻 В Go захотели поддержку GOARM64=v9.6 В трекере Go появилось предложение №80402. Разработчик просит добави…","articleBody":"🧑💻 В Go захотели поддержку GOARM64=v9.6\n\nВ трекере Go появилось предложение №80402. Разработчик просит добавить новое значение переменной GOARM64 со значением v9.6 и тег сборки arm64.v9.6, чтобы тулчейн умел собирать под архитектуру Armv9.6-A.\n\nВместе с версией предлагают включать набор инструкций FEAT_CMPBR автоматически. Он объединяет сравнение и условный переход в одну операцию, в Armv9.6-A обязателен, поэтому отдельная опция не нужна. По умолчанию поведение не меняется, значение пригодится тем, кто собирает под свежие чипы на Armv9.6-A.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoLive","datePublished":"2026-07-15T18:03:15Z","dateModified":"2026-07-15T18:03:15Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2749},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":1}]}},{"@type":"ListItem","position":4,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7406","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7406","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7406","headline":"🔥 Курс «Разработка ИИ-агентов» стартовал, но вы еще успеваете присоединиться! Мы только начали, а первый прак…","articleBody":"🔥 Курс «Разработка ИИ-агентов» стартовал, но вы еще успеваете присоединиться!\n\nМы только начали, а первый практический воркшоп пройдет только 23 июля. До этого времени вы спокойно успеете изучить материалы и нагнать группу. \n\n💼 Главная фишка: финальный проект в портфолио:\n\nВ финальном проекте вы сможете выбрать один из двух вариантов: реализовать свою идею или решить задачу от партнера курса — крупной российской финтех-компании. Вы будете работать с датасетом, построенным по реальным сценариям, получите бизнес-контекст и продовые ограничения. В результате соберете AI-агента, который станет сильным проектом для портфолио.\n\n🎁 Упомяните менеджеру специальное предложение «3 курса по цене 1»: Берете VIP-тариф — получаете курс «Разработка ИИ-агентов», хардкорный «AgentOps» и ещё один курс на выбор. Выгода 129.000 ₽!\n\nДвери потока вот-вот закроются окончательно. Успейте забрать стек курсов и начать работу над реальным проектом \n\n🔗 Занять место и забрать 3 курса","datePublished":"2026-07-15T15:00:46Z","dateModified":"2026-07-15T15:00:46Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"image":["https://n3.tlmtr.cc/p/_ZNyF2FMPDZDl4JeCxdAvN_AQsZYAq_Ld1rqsjja5fCE?ty=l"],"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2626},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":3}]}},{"@type":"ListItem","position":5,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7405","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7405","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7405","headline":"⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 2, ручной GC и код без аллокаций В первой части мы ра…","articleBody":"⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 2, ручной GC и код без аллокаций\n\nВ первой части мы разобрали связку GOGC=off и GOMEMLIMIT. Она подходит большинству сервисов и не требует переписывать код. Но есть задачи, где даже редкие циклы сборки в неудачный момент неприемлемы. Торговый бот в момент котировки, игровой сервер внутри тика, обработчик, у которого хвостовые задержки важнее среднего времени ответа.\n\nДля таких случаев есть два более жёстких варианта. \n\n➡️ Вариант первый, ручные циклы в окнах простоя\n\nИдея простая. Вы выключаете автоматический триггер и запускаете сборку сами, но только тогда, когда пауза никому не мешает. Между тиками, между батчами, вне торговой сессии:\ndebug.SetGCPercent(-1)\n\nfor {\n batch := queue.Fetch()\n process(batch) // на этом участке GC не вмешивается\n\n if idle() {\n runtime.GC()\n debug.FreeOSMemory() // ещё и вернуть память операционной системе\n }\n}\n\nruntime.GC() выполняет полный цикл синхронно и возвращает управление, когда он закончен. debug.FreeOSMemory() делает то же самое и дополнительно отдаёт освободившиеся страницы ОС, что полезно, если вы платите за резидентную память, а не за виртуальную.\n\nВыигрыш в том, что паузы переезжают туда, где они бесплатны. Хвост распределения задержек становится заметно ровнее, потому что в горячем пути нет ни маркировки, ни барьеров записи.\n\nРиск в том, что окно простоя может не наступить. Всплеск нагрузки, и память растёт без ограничений. Поэтому такую схему почти всегда страхуют. Либо тем же GOMEMLIMIT как аварийным тормозом, либо явной проверкой порога:\nvar m runtime.MemStats\n\nfunc maybeCollect(limit uint64) {\n runtime.ReadMemStats(&m) // это stop the world, не вызывайте в горячем цикле\n if m.HeapAlloc > limit {\n runtime.GC()\n }\n}\n\nruntime.ReadMemStats сам по себе останавливает мир, так что вызывать его надо по таймеру раз в секунду, а не на каждой итерации.\n\n➡️ Вариант второй, программа без аллокаций\n\nТеоретически самый чистый путь. Если после инициализации программа не аллоцирует в куче вообще, сборщику нечего собирать и GOGC=off безопасен буквально навсегда.\n\nЭто означает выделение всех буферов на старте, переиспользование через sync.Pool или собственные пулы, отказ от fmt в горячем пути, отказ от интерфейсов там, где значение убегает в кучу, работу со срезами фиксированной ёмкости вместо растущего append.\n\nПроверять это надо не на глаз, а инструментами:\ngo build -gcflags='-m' ./... // что именно убегает в кучу\ngo test -bench=. -benchmem // столбец allocs/op должен быть нулевым\n\nИ регрессионный тест, который падает, как только счётчик аллокаций перестал быть нулём:\nfunc TestNoAllocs(t *testing.T) {\n allocs := testing.AllocsPerRun(1000, func() {\n process(input) // горячий путь\n })\n if allocs != 0 {\n t.Fatalf(\"ожидали 0 аллокаций, получили %v\", allocs)\n }\n}\n\nЧестное предупреждение. Держать такое состояние в живом проекте тяжело. Одна безобидная строка логирования, один err.Error() в неудачном месте, и аллокации возвращаются. Обычно так пишут узкое ядро системы, а весь остальной сервис живёт с обычным GC.\n\nКогда всё это оправдано\n\nВыключать сборщик стоит только после измерений. Профиль показывает заметное время в runtime.gcBgMarkWorker, трассировка показывает всплески задержек ровно на циклах сборки, или программа настолько короткоживущая, что сборка просто не успевает окупиться.\nВо всех остальных случаях достаточно поднять GOGC до 200 или 400. Это даёт большую часть выигрыша и не создаёт риска OOM.\n\nДолгоживущая программа с GOGC=off возможна, если вы не оставляете систему без тормозов совсем. GOMEMLIMIT подходит почти всем и не требует менять код. Ручные вызовы runtime.GC() в окнах простоя дают самые ровные задержки, но нуждаются в страховке по памяти. Код без аллокаций работает вечно, но живёт только под постоянным присмотром бенчмарков.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoDeep","datePublished":"2026-07-15T13:02:16Z","dateModified":"2026-07-15T13:02:16Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":5,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2242},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":9},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":22},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":5}]}},{"@type":"ListItem","position":6,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7404","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7404","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7404","headline":"😋 Топ-вакансий для Go-разработчиков за неделю Go-разработчик — от 365 000 ₽, Удаленно (Москва) Golang разрабо…","articleBody":"😋 Топ-вакансий для Go-разработчиков за неделю \n\nGo-разработчик — от 365 000 ₽, Удаленно (Москва)\n\nGolang разработчик — офис в Москве\n\nSenior Backend Engineer — от 450 000 ₽, удаленно (Москва)\n\n➡️ Еще больше топовых вакансий — в нашем канале Go jobs\n\n🐸 Библиотека Go-разработчика\n\n#GoWork","datePublished":"2026-07-15T07:02:30Z","dateModified":"2026-07-15T07:02:30Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2688},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":1},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":2}]}},{"@type":"ListItem","position":7,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7403","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7403","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7403","headline":"🔒 age, шифрование файлов без конфигов и без GPG Надо зашифровать бэкап, дамп базы или файл с секретами. Класс…","articleBody":"🔒 age, шифрование файлов без конфигов и без GPG\n\nНадо зашифровать бэкап, дамп базы или файл с секретами. Классический ответ это GPG, а вместе с ним keyring, сеть доверия, десяток флагов и вывод, который не прочитать без документации. Для одной операции это перебор.\n\nage делает ровно эту задачу и ничего больше. Инструмент шифрования файлов, формат и Go библиотека от Филиппо Вальсорды. Маленькие явные ключи, никаких опций конфигурации, поведение в духе UNIX. Формат описан спецификацией age-encryption.org/v1.\n\nБазовый сценарий\n\nТри команды:\n$ age-keygen -o key.txt\nPublic key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p\n\n$ tar cvz ~/data | age -r age1ql3z7... > data.tar.gz.age\n\n$ age -d -i key.txt data.tar.gz.age > data.tar.gz\n\nПубличный ключ это одна строка с префиксом age1, приватный одна строка с префиксом AGE-SECRET-KEY-1. Никакого keyring и никакого состояния на диске кроме файла с ключом.\n\nЧто ещё умеет\n\nФлаг -r можно повторять, тогда файл расшифрует любой из получателей. Список получателей удобнее держать файлом и передавать через -R. Флаг -p шифрует паролем, причём при пустом вводе age сгенерирует стойкую фразу сам. Флаг -a даёт текстовый PEM вывод, если файл надо вставить в письмо или в YAML. При расшифровке тип файла определяется автоматически.\n\nПриятно, что можно шифровать на обычные SSH ключи:\n$ age -R ~/.ssh/id_ed25519.pub example.jpg > example.jpg.age\n$ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg\n\nОтсюда трюк с GitHub, где публичные ключи лежат по адресу вида github.com/username.keys:\n$ curl https://github.com/benjojo.keys | age -R - example.jpg > example.jpg.age\n\nС версии 1.3.0 есть гибридные постквантовые ключи через age-keygen -pq. Цена в том, что публичный ключ получателя разрастается примерно до двух тысяч символов.\n\nКак библиотека\n\nCLI это обёртка над пакетом filippo.io/age:\nrecipient, _ := age.ParseX25519Recipient(pubKey)\n\nout := &bytes.Buffer{}\nw, err := age.Encrypt(out, recipient)\nif err != nil {\n log.Fatal(err)\n}\nio.WriteString(w, \"секретные данные\")\nw.Close() // обязателен, иначе не запишется финальный блок\n\nВсё построено на io.Reader и io.Writer, поэтому поток по сети шифруется так же, как строка в памяти. Расшифровка через age.Decrypt с age.ParseX25519Identity.\n\nСтавится из репозиториев почти везде, либо командой go install filippo.io/age/cmd/...@latest.\n\nage стоит брать, когда нужно зашифровать файл и не хочется тащить модель доверия GPG. Подписей, отзыва ключей и сети доверия здесь нет и не будет. Это не замена GPG во всём, а замена в той задаче, ради которой его чаще всего и запускают.\n\n➡️ Репозиторий\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoToProduction","datePublished":"2026-07-14T18:01:46Z","dateModified":"2026-07-14T18:01:46Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":2,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2669},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":11},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":44},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2}]}},{"@type":"ListItem","position":8,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7402","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7402","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7402","headline":"⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 1, GOMEMLIMIT Короткий ответ: да, но не так, как обыч…","articleBody":"⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 1, GOMEMLIMIT\n\nКороткий ответ: да, но не так, как обычно себе это представляют. Полностью выключенный сборщик мусора почти всегда означает, что программа рано или поздно съест всю память. Работающие варианты сводятся к тому, что GC не выключается совсем, а перестаёт запускаться по росту кучи и начинает запускаться по вашим правилам.\n\nВ этой части разберём, что делает GOGC=off, почему наивный вариант падает, и самый практичный способ жить без сборок, связку с GOMEMLIMIT.\n\n➡️ Что делает GOGC\n\nGOGC задаёт, насколько куча должна вырасти относительно живых данных, прежде чем начнётся следующий цикл сборки. При значении по умолчанию 100 сборка стартует, когда куча удвоилась относительно объёма живых объектов после прошлого цикла. При GOGC=200 цикл будет реже и памяти уйдёт больше. При GOGC=off триггер по росту кучи пропадает совсем.\n\nТо же самое можно сделать из кода:\nimport \"runtime/debug\"\n\nfunc main() {\n debug.SetGCPercent(-1) // эквивалент GOGC=off\n // ...\n}\n\nВажно понимать, что аллокатор при этом никуда не девается. Программа продолжает выделять память, просто освобождать её никто не будет. Каждый временный слайс, каждая строка от fmt.Sprintf, каждый заголовок HTTP запроса остаются в куче навсегда. Для батча, который живёт три секунды и завершается, это идеально. Для сервиса, который работает неделями, это утечка по определению.\n\n➡️ Почему наивный вариант падает\n\nВозьмём типичный HTTP сервис. Даже если ваш собственный код не аллоцирует, стандартная библиотека аллоцирует за вас. net/http создаёт объекты на каждый запрос, encoding/json создаёт их на каждый декод, драйвер базы создаёт их на каждый ряд. При тысяче запросов в секунду и паре килобайт мусора на запрос вы получаете около двух мегабайт в секунду, то есть примерно семь гигабайт в час. Дальше приходит OOM killer.\n\nПоэтому вопрос не в том, можно ли выключить GC, а в том, чем заменить триггер, который вы выключили.\n\n➡️ GOMEMLIMIT как замена триггера\n\nGOMEMLIMIT — самый практичный подход и он появился в Go 1.19. Комбинация GOGC=off и GOMEMLIMIT даёт сборщик, который не реагирует на рост кучи вообще, но запускается, когда потребление памяти приближается к заданному лимиту.\nGOGC=off GOMEMLIMIT=4GiB ./myservice\n\nИли из кода:\ndebug.SetGCPercent(-1)\ndebug.SetMemoryLimit(4 << 30) // 4 GiB\n\nЧто вы получаете. Пока памяти хватает, циклов сборки нет совсем, а значит нет накладных расходов на маркировку и барьеры записи. Как только программа подходит к лимиту, GC включается и удерживает потребление около него. Куча живёт в стабильном состоянии, а не пилой от нуля до удвоения.\n\nЧто вы теряете. Если объём живых данных сам по себе дорастает до лимита, GC начнёт запускаться непрерывно и программа уйдёт в смерть от сборки, когда почти всё время уходит на бесполезные циклы. Лимит поэтому ставят с запасом относительно ожидаемого объёма живых данных, а не впритык к памяти контейнера. Разумная практика ставить GOMEMLIMIT процентов на десять ниже лимита пода, чтобы GC успел среагировать раньше, чем это сделает cgroup.\n\nЕщё одна тонкость. GOMEMLIMIT учитывает всю память рантайма, включая стеки горутин и служебные структуры, но не учитывает то, что выделено вне рантайма, например через cgo или mmap. Если такого много, лимит надо занижать дополнительно.\n\n➡️ Про ballast\n\nРаньше был популярен трюк с большим фиктивным слайсом, который выделяли на старте, чтобы поднять порог срабатывания GC. Сейчас он не нужен. GOMEMLIMIT решает ту же задачу.\n\nИтог первой части\n\nGOGC=off сам по себе это не оптимизация, а отложенный OOM. Но GOGC=off вместе с GOMEMLIMIT вполне живёт в проде годами. Сборщик молчит на нормальной нагрузке и вступает в дело только у границы, которую вы задали сами.\n\nВо второй части посмотрим на два более жёстких варианта. Ручные вызовы runtime.GC() в окнах простоя и код, который вообще не аллоцирует после старта.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoDeep","datePublished":"2026-07-14T13:02:32Z","dateModified":"2026-07-14T13:02:32Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":6,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2174},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":8},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":22},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":6}]}},{"@type":"ListItem","position":9,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7401","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7401","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7401","headline":"🔥 Стартуем СЕГОДНЯ! Новый поток курса «Разработка ИИ-агентов» открыт По этому поводу мы решили выложить закры…","articleBody":"🔥 Стартуем СЕГОДНЯ! Новый поток курса «Разработка ИИ-агентов» открыт\n\nПо этому поводу мы решили выложить закрытую запись одного из уроков из программы. Найти её в поиске YouTube нельзя — она доступна только по ссылке и всем, кто будет на курсе.\n\nВнутри глубокий разбор LLM от Алексея Яндутова (Senior ML-инженер, развивал ответы «Алисы» и «Нейро» в Яндексе). Учимся получать точный результат без галлюцинаций.\n\nЧто внутри урока:\n\n- Устройство LLM.\n- Рабочие шаблоны промптов (Persona, Chain-of-Thought и др.).\n- Разбор реального кейса Яндекса. Как автоматизировать разметку, обойти качество людей на 5% и срезать косты на 60%.\n\nПосле просмотра вы поймете, когда хватает промпт-инжиниринга, а когда нужен RAG или fine-tuning.\n\n👉Смотреть закрытый урок на YouTube\n\nПонравился урок? Переходите на новый уровень! Оставляйте заявку на курс, чтобы научиться проектировать надежные автономные системы. Обучение началось, но вы еще успеваете присоединиться.\n\n🔗 Занять место на курсе","datePublished":"2026-07-14T08:50:19Z","dateModified":"2026-07-14T08:50:19Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"image":["https://n3.tlmtr.cc/p/_KSyVFPAGrdZJ9o6uXrQRjzQ_AQVEqaYcqA9yOiMbD4o?ty=l"],"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2207},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":1}]}},{"@type":"ListItem","position":10,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7400","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7400","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7400","headline":"📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle","articleBody":"📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoGiggle","datePublished":"2026-07-14T06:59:54Z","dateModified":"2026-07-14T06:59:54Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2506},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":11},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":13}]}},{"@type":"ListItem","position":11,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7399","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7399","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7399","headline":"🎸 Конференция, которая заканчивается концертом ИТ-Пикник 2026 — это не только доклады. Музыкальный хедлайнер…","articleBody":"🎸 Конференция, которая заканчивается концертом\n\nИТ-Пикник 2026 — это не только доклады. Музыкальный хедлайнер — LAB, шоу Антона Беляева и команды Therr Maitz: популярные треки в новых аранжировках с оркестром и хором. А ещё ИТ-Квартирник — отдельная сцена для музыкантов из мира технологий, где семь команд из опен-колла борются за право выйти на главную сцену с Pompeya.\n\n➡️ Собрали всё, что известно о фестивале\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика","datePublished":"2026-07-13T17:59:54Z","dateModified":"2026-07-13T17:59:54Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2526},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":1}]}},{"@type":"ListItem","position":12,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7393","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7393","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7393","headline":"👀 20 ошибок, которые пропустит компилятор Собрали в карточках ошибки, которые можно отловить на код-ревью. 📍…","articleBody":"👀 20 ошибок, которые пропустит компилятор\n\nСобрали в карточках ошибки, которые можно отловить на код-ревью.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoVisual","datePublished":"2026-07-13T12:59:54Z","dateModified":"2026-07-13T12:59:54Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":2,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2812},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":10},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":59},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":2}]}},{"@type":"ListItem","position":13,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7387","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7387","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7387","headline":"👀 20 ошибок, которые пропустит компилятор Собрали в карточках ошибки, которые можно поймать на код-ревью. 📍 Н…","articleBody":"👀 20 ошибок, которые пропустит компилятор\n\nСобрали в карточках ошибки, которые можно поймать на код-ревью. \n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoVisual","datePublished":"2026-07-13T08:59:54Z","dateModified":"2026-07-13T09:02:23Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":1}]}},{"@type":"ListItem","position":14,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7386","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7386","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7386","headline":"🚀 Уже завтра стартует новый поток курса «ИИ-агенты»! Мы собрали мощнейший состав преподавателей. Учить вас пр…","articleBody":"🚀 Уже завтра стартует новый поток курса «ИИ-агенты»!\n\nМы собрали мощнейший состав преподавателей. Учить вас проектировать архитектуру и собирать продакшн-агентов будут инженеры и исследователи из топовых IT-компаний.\n\nСтарт уже завтра!\n\nСомневаетесь, подойдет ли вам программа и подача? Начните с бесплатного демо-урока!\n\nВсего за 2 часа вы заглянете под капот ИИ-агента, поймете, чем мышление модели отличается от ее ответа, и научите систему чинить собственный код. Это идеальный способ протестировать нашу платформу перед покупкой.\n\n🔗 Пройти демо-урок и занять место на курсе","datePublished":"2026-07-13T08:43:16Z","dateModified":"2026-07-13T08:43:16Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"image":["https://n2.tlmtr.cc/p/__Dh9qFnJ-xnVPEc1MOk_6Vgj9ywBvF0tS7uSmYfVSK8?ty=l"],"commentCount":1,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2264},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":4},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":1}]}},{"@type":"ListItem","position":15,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7385","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7385","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7385","headline":"💬 События публикуются дважды Сервис сохраняет заказ в БД и сразу публикует событие OrderCreated. Выглядит лог…","articleBody":"💬 События публикуются дважды\n\nСервис сохраняет заказ в БД и сразу публикует событие OrderCreated. Выглядит логично, но БД и очередь это две отдельные системы.\n\nЧто может произойти: БД коммитилась, но публикация упала. Заказ есть, события нет. Клиент повторяет запрос из за таймаута. Событие публикуется еще раз. Нижестоящий сервис видит два события и создает два заказа вместо одного.\n\n➡️ Решение: Outbox паттерн\n\nСохраняем заказ и событие в одной БД транзакции. Отдельный диспетчер читает неотправленные события и публикует их позже. Если диспетчер упадет или повторится, событие уже в БД и не потеряется.\n// В одной транзакции\nBEGIN\n INSERT INTO orders ...\n INSERT INTO outbox ...\nCOMMIT\n\n// Отдельно\nfunc dispatchOutbox() {\n events := store.GetUnsent()\n for _, e := range events {\n publisher.Send(e)\n store.MarkSent(e.ID)\n }\n}\n\n➡️ Ключевые моменты\n\nКаждое событие должно иметь уникальный ID. Потребители должны быть идемпотентные (игнорировать дубликаты). Outbox паттерн гарантирует, что событие не потеряется, но не гарантирует ровно одну доставку. Это нормально, если потребители правильно обрабатывают дубликаты.\n\n➡️ Что делать\n\nДобавьте таблицу outbox. Вставляйте заказ и событие одной транзакцией. Запустите диспетчер, который периодически отправляет события из outbox. Добавьте уникальный event_id потребителям для фильтрации дубликатов.\n\nГраница между микросервисами это самое опасное место. Outbox паттерн это простой способ сделать ее безопаснее.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoToProduction","datePublished":"2026-07-13T06:59:54Z","dateModified":"2026-07-13T06:59:54Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2096},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":10},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":20}]}},{"@type":"ListItem","position":16,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7384","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7384","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7384","headline":"📰 Дайджест недели Здесь нет дождей, здесь только новости — Go теперь компилирует TypeScript Microsoft выкатил…","articleBody":"📰 Дайджест недели\n\nЗдесь нет дождей, здесь только новости\n\n— Go теперь компилирует TypeScript\n\nMicrosoft выкатила TypeScript 7.0 — компилятор целиком переписан с TS на Go. Итог: сборки быстрее в 8-12 раз при меньшем потреблении памяти на 6-26%\n\n— Ускорение in-memory кеша до 8 раз\n\n— Фреймворк, где файловая система это карта маршрутов\n\n— Результат джуна близок к нулю\n\n— Бонусы-призраки и грейды из параллельной вселенной\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoLive","datePublished":"2026-07-12T14:59:55Z","dateModified":"2026-07-12T14:59:55Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2196},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":5}]}},{"@type":"ListItem","position":17,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7383","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7383","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7383","headline":"⭐️ Тип в композитных литералах станет необязательным Предложение №12854 висело в трекере с 2015 года и наконе…","articleBody":"⭐️ Тип в композитных литералах станет необязательным\n\nПредложение №12854 висело в трекере с 2015 года и наконец получило статус accepted. \n\nТеперь тип литерала можно будет опускать везде, где компилятор выводит его из контекста:\nvar x []string = {\"a\", \"b\", \"c\"}\nreturn {}, err\ncompress.NewReader(r, {Level: compress.BestSpeed})\nitems = append(items, {id, obj, false})\n\nЗапись a := {1, 2, 3} останется ошибкой, слева нет явного типа и выводить нечего.\n\nВыигрывают табличные тесты, структуры опций и код с protobuf, где имена типов повторяются десятками. Спор о читаемости команда закрыла так. gofmt не будет принудительно удалять типы, стиль сложится сам, а gopls получит подсказки, которые покажут пропавшее имя типа прямо в редакторе.\n\nВ Go 1.27 фича не попадёт. Изменение в компиляторе простое, но нужно обновить экосистему инструментов, поэтому ориентир это Go 1.28.\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика","datePublished":"2026-07-12T08:59:55Z","dateModified":"2026-07-12T08:59:55Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":5,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2358},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":8},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":10},{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":5}]}},{"@type":"ListItem","position":18,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7382","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7382","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7382","headline":"📍 Навигация: Вакансии • Задачи • Собесы 🐸 Библиотека Go-разработчика #GoGiggle","articleBody":"📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoGiggle","datePublished":"2026-07-11T17:59:55Z","dateModified":"2026-07-11T17:59:55Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2343},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":12},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":8}]}},{"@type":"ListItem","position":19,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7381","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7381","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7381","headline":"🛩 FlightRecorder в проде В Go 1.25 в стандартную библиотеку завезли trace.FlightRecorder — кольцевой буфер тр…","articleBody":"🛩 FlightRecorder в проде\n\nВ Go 1.25 в стандартную библиотеку завезли trace.FlightRecorder — кольцевой буфер трассировки, который постоянно крутится в памяти, а по команде Snapshot() отдаёт последние N секунд событий рантайма. Идея: сэмплирующий профайлер видит «среднюю температуру», а тут вы получаете полную картину именно того момента, когда всё пошло не так.\n\nПара примеров:\n\n▪️ Ловля хвостовых задержек\n\nМидлварь замеряет время обработки запроса, и если оно перевалило за исторический p95 (или прилетела 500-ка) — асинхронно дёргается снапшот.\n\nБинарный дамп улетает в S3, ссылка логируется в Grafana. Сработал алерт → кликнули по ссылке → скачали дамп → go tool trace slow-trace.out. \n\n▪️ Проблемы шедулера и GC\n\nВсё, что живёт между сэмплами профайлера: залипания горутин, GC assist, вытеснение горутин с P — на трассе это видно, в профиле нет.\n\nНо есть и обратная сторона: формат данных не дружит с Pyroscope и Datadog, поэтому дамп нельзя просто открыть в дашборде — приходится вручную гонять go tool по конкретному поду. А когда подов больше тысячи, удовольствие ниже среднего. Инструмент мощный, эргономика — пока нет.\n\n💬 А вы пробовали FlightRecorder? Для чего включали, что нашли такого, чего не показал pprof, и как вытаскивали трейсы с прода?\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика\n\n#GoToProduction","datePublished":"2026-07-11T14:59:55Z","dateModified":"2026-07-11T14:59:55Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2400},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":12},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":51}]}},{"@type":"ListItem","position":20,"item":{"@type":"SocialMediaPosting","@id":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7380","url":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7380","mainEntityOfPage":"https://telemetr.io/ch/channels/1465826763-goproglib/posts/7380","headline":"🔮 Прогноз для IT-рынка после 2027 года Кажется, что рынок умер: вакансий меньше на 20-35%, зарплаты растут ме…","articleBody":"🔮 Прогноз для IT-рынка после 2027 года\n\nКажется, что рынок умер: вакансий меньше на 20-35%, зарплаты растут медленнее инфляции, hh-индекс в IT перевалил за 14. Но если наложить сегодняшний спад на три предыдущих цикла — доткомы, 2008-й и пандемию — картина выглядит иначе.\n\nЧто будет дальше: где ждать взрывного роста вакансий в 2028-2030, почему разрыв в зарплатах может достичь 50-120% и что делать в ближайшие полтора года, чтобы оказаться на правильной стороне этого разрыва.\n\n➡️ Ответы в статье\n\n📍 Навигация: Вакансии • Задачи • Собесы\n\n🐸 Библиотека Go-разработчика","datePublished":"2026-07-11T08:59:55Z","dateModified":"2026-07-11T08:59:55Z","author":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"publisher":{"@type":"Organization","name":"Библиотека Go-разработчика | Golang","url":"https://telemetr.io/ch/channels/1465826763-goproglib","image":"https://img.telemetr.io/c/1Bcsv9/5285275279037683160?ty=x"},"commentCount":0,"interactionStatistic":[{"@type":"InteractionCounter","interactionType":"https://schema.org/ViewAction","userInteractionCount":2294},{"@type":"InteractionCounter","interactionType":"https://schema.org/LikeAction","userInteractionCount":5},{"@type":"InteractionCounter","interactionType":"https://schema.org/ShareAction","userInteractionCount":10}]}}]}
🤩 Go открыт для разработки 1.28
Команда Go сообщила о статусе релиза Go 1.27, он скоро уйдёт в релиз, а основная ветка уже открыта для общей разработки Go 1.28.
Пока идёт стабилизация 1.27. В треде разработчики уже расписали планы на следующую версию.
Будут чинить баги корректности компилятора, добавлять инкрементальные оптимизации в regalloc и планировщик, а также убирать рукописный ассемблер в пользу чистого Go.
Будут переработаны узкие места масштабируемости сборщика мусора при работе на более чем 256 ядрах и проведут эксперименты с NUMA осведомлённостью Green Tea.
➡️ Источник
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoLive
🛡 Защита от SQL инъекций и XSS в Go
Оба типа атак растут из одной ошибки. Мы склеиваем строку из данных пользователя и отдаём её движку, который умеет исполнять код. База данных видит SQL, браузер видит HTML или JavaScript. Данные внезапно становятся командами.
Разберём, как этого не допускать на практике, и что спросят на собеседовании.
💉 SQL инъекции
Опасный код выглядит так:
query := fmt.Sprintf("SELECT id, email FROM users WHERE email = '%s'", email)
row := db.QueryRow(query)
Если в email придёт ' OR 1=1 --, условие развалится и вернётся вся таблица. Строка форматируется до того, как попадёт в базу, поэтому никакой защиты тут нет.
Правильный вариант передаёт значения отдельно от текста запроса:
row := db.QueryRowContext(ctx,
"SELECT id, email FROM users WHERE email = $1", email)
Драйвер отправляет запрос и параметры разными полями протокола. Значение уже не может изменить структуру запроса, потому что база разбирает синтаксис до подстановки данных. Синтаксис плейсхолдера зависит от драйвера, в pgx и lib/pq это $1, в go-sql-driver/mysql это ?.
Что нельзя параметризовать
Плейсхолдеры работают только для значений. Имя таблицы, имя колонки, направление сортировки так подставить не получится. Здесь помогает белый список:
var allowedSort = map[string]string{
"created": "created_at",
"email": "email",
}
column, ok := allowedSort[r.URL.Query().Get("sort")]
if !ok {
column = "created_at"
}
query := fmt.Sprintf("SELECT id FROM users ORDER BY %s DESC LIMIT 50", column)
Форматирование строки тут безопасно, потому что в column попадает только заранее известное значение из карты, а не пользовательский ввод.
Отдельно стоит помнить про IN. Список плейсхолдеров придётся собрать самому:
placeholders := make([]string, len(ids))
args := make([]any, len(ids))
for i, id := range ids {
placeholders[i] = fmt.Sprintf("$%d", i+1)
args[i] = id
}
query := "SELECT id FROM users WHERE id IN (" + strings.Join(placeholders, ",") + ")"
rows, err := db.QueryContext(ctx, query, args...)
В pgx проще передать массив через = ANY($1).
Билдеры вроде squirrel и ORM вроде gorm подставляют аргументы сами. Но у обоих есть методы для сырых кусков SQL, и туда пользовательский ввод класть нельзя. gorm спасает не сам по себе, а только пока мы не пишем Where(fmt.Sprintf(...)).
Дополнительные меры, которые уменьшают ущерб при ошибке. Отдельный пользователь базы с минимальными правами, без DROP и без доступа к чужим схемам. Логи запросов без подстановленных значений. Ограничение на размер входных полей.
🔪 XSS
Та же логика, только теперь опасный движок это браузер. Если мы вставим пользовательский текст прямо в HTML, тег <script> из комментария выполнится у всех, кто открыл страницу.
Плохо:
Ключевое отличие в пакете. html/template экранирует данные с учётом контекста, text/template не экранирует ничего. Импорт text/template в веб хендлере это готовая дыра, и на собеседовании про это спрашивают почти всегда.
Контекстность означает, что шаблонизатор смотрит, куда именно попадает значение. Внутри тега это HTML экранирование, внутри атрибута другое, внутри href проверка схемы, внутри блока <script> экранирование по правилам JavaScript.
Один и тот же {{ .Value }} даст разный вывод:
Строка javascript:alert(1) в href превратится в #ZgotmplZ, то есть ссылка просто не сработает.
➡️ Где защита отключается
Типы template.HTML, template.JS, template.URL говорят шаблонизатору доверять содержимому и не трогать его. Это законная возможность, но применять её к данным пользователя нельзя:
// так делать нельзя
data.Bio = template.HTML(userInput)
Если пользователю действительно нужен HTML, например разметка в комментариях, содержимое надо чистить санитайзером:
import "github.com/microcosm-cc/bluemonday"
p := bluemonday.UGCPolicy()
safe := template.HTML(p.Sanitize(userInput))
bluemonday работает по белому списку тегов и атрибутов, всё остальное вырезает.
➡️ API и заголовки
Для JSON ответов достаточно encoding/json, он экранирует <, > и & в escape последовательности. Но заголовок ставить обязательно, иначе браузер может угадать тип и отрендерить ответ как HTML.
Хорошая практика добавить Content-Security-Policy, который запрещает инлайновые скрипты. Он не заменяет экранирование, но снижает шанс, что случайная дыра превратится в кражу сессий. Куки сессии стоит помечать HttpOnly, тогда украденный скрипт до них не доберётся.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoDeep
🧑💻 В Go захотели поддержку GOARM64=v9.6
В трекере Go появилось предложение №80402. Разработчик просит добавить новое значение переменной GOARM64 со значением v9.6 и тег сборки arm64.v9.6, чтобы тулчейн умел собирать под архитектуру Armv9.6-A.
Вместе с версией предлагают включать набор инструкций FEAT_CMPBR автоматически. Он объединяет сравнение и условный переход в одну операцию, в Armv9.6-A обязателен, поэтому отдельная опция не нужна. По умолчанию поведение не меняется, значение пригодится тем, кто собирает под свежие чипы на Armv9.6-A.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoLive
🔥 Курс «Разработка ИИ-агентов» стартовал, но вы еще успеваете присоединиться!
Мы только начали, а первый практический воркшоп пройдет только 23 июля. До этого времени вы спокойно успеете изучить материалы и нагнать группу.
💼 Главная фишка: финальный проект в портфолио:
В финальном проекте вы сможете выбрать один из двух вариантов: реализовать свою идею или решить задачу от партнера курса — крупной российской финтех-компании. Вы будете работать с датасетом, построенным по реальным сценариям, получите бизнес-контекст и продовые ограничения. В результате соберете AI-агента, который станет сильным проектом для портфолио.
🎁 Упомяните менеджеру специальное предложение «3 курса по цене 1»: Берете VIP-тариф — получаете курс «Разработка ИИ-агентов», хардкорный «AgentOps» и ещё один курс на выбор. Выгода 129.000 ₽!
Двери потока вот-вот закроются окончательно. Успейте забрать стек курсов и начать работу над реальным проектом
🔗 Занять место и забрать 3 курса
⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 2, ручной GC и код без аллокаций
В первой части мы разобрали связку GOGC=off и GOMEMLIMIT. Она подходит большинству сервисов и не требует переписывать код. Но есть задачи, где даже редкие циклы сборки в неудачный момент неприемлемы. Торговый бот в момент котировки, игровой сервер внутри тика, обработчик, у которого хвостовые задержки важнее среднего времени ответа.
Для таких случаев есть два более жёстких варианта.
➡️ Вариант первый, ручные циклы в окнах простоя
Идея простая. Вы выключаете автоматический триггер и запускаете сборку сами, но только тогда, когда пауза никому не мешает. Между тиками, между батчами, вне торговой сессии:
debug.SetGCPercent(-1)
for {
batch := queue.Fetch()
process(batch) // на этом участке GC не вмешивается
if idle() {
runtime.GC()
debug.FreeOSMemory() // ещё и вернуть память операционной системе
}
}
runtime.GC() выполняет полный цикл синхронно и возвращает управление, когда он закончен. debug.FreeOSMemory() делает то же самое и дополнительно отдаёт освободившиеся страницы ОС, что полезно, если вы платите за резидентную память, а не за виртуальную.
Выигрыш в том, что паузы переезжают туда, где они бесплатны. Хвост распределения задержек становится заметно ровнее, потому что в горячем пути нет ни маркировки, ни барьеров записи.
Риск в том, что окно простоя может не наступить. Всплеск нагрузки, и память растёт без ограничений. Поэтому такую схему почти всегда страхуют. Либо тем же GOMEMLIMIT как аварийным тормозом, либо явной проверкой порога:
var m runtime.MemStats
func maybeCollect(limit uint64) {
runtime.ReadMemStats(&m) // это stop the world, не вызывайте в горячем цикле
if m.HeapAlloc > limit {
runtime.GC()
}
}
runtime.ReadMemStats сам по себе останавливает мир, так что вызывать его надо по таймеру раз в секунду, а не на каждой итерации.
➡️ Вариант второй, программа без аллокаций
Теоретически самый чистый путь. Если после инициализации программа не аллоцирует в куче вообще, сборщику нечего собирать и GOGC=off безопасен буквально навсегда.
Это означает выделение всех буферов на старте, переиспользование через sync.Pool или собственные пулы, отказ от fmt в горячем пути, отказ от интерфейсов там, где значение убегает в кучу, работу со срезами фиксированной ёмкости вместо растущего append.
Проверять это надо не на глаз, а инструментами:
go build -gcflags='-m' ./... // что именно убегает в кучу
go test -bench=. -benchmem // столбец allocs/op должен быть нулевым
И регрессионный тест, который падает, как только счётчик аллокаций перестал быть нулём:
func TestNoAllocs(t *testing.T) {
allocs := testing.AllocsPerRun(1000, func() {
process(input) // горячий путь
})
if allocs != 0 {
t.Fatalf("ожидали 0 аллокаций, получили %v", allocs)
}
}
Честное предупреждение. Держать такое состояние в живом проекте тяжело. Одна безобидная строка логирования, один err.Error() в неудачном месте, и аллокации возвращаются. Обычно так пишут узкое ядро системы, а весь остальной сервис живёт с обычным GC.
Когда всё это оправдано
Выключать сборщик стоит только после измерений. Профиль показывает заметное время в runtime.gcBgMarkWorker, трассировка показывает всплески задержек ровно на циклах сборки, или программа настолько короткоживущая, что сборка просто не успевает окупиться.
Во всех остальных случаях достаточно поднять GOGC до 200 или 400. Это даёт большую часть выигрыша и не создаёт риска OOM.
Долгоживущая программа с GOGC=off возможна, если вы не оставляете систему без тормозов совсем. GOMEMLIMIT подходит почти всем и не требует менять код. Ручные вызовы runtime.GC() в окнах простоя дают самые ровные задержки, но нуждаются в страховке по памяти. Код без аллокаций работает вечно, но живёт только под постоянным присмотром бенчмарков.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoDeep
🔒 age, шифрование файлов без конфигов и без GPG
Надо зашифровать бэкап, дамп базы или файл с секретами. Классический ответ это GPG, а вместе с ним keyring, сеть доверия, десяток флагов и вывод, который не прочитать без документации. Для одной операции это перебор.
age делает ровно эту задачу и ничего больше. Инструмент шифрования файлов, формат и Go библиотека от Филиппо Вальсорды. Маленькие явные ключи, никаких опций конфигурации, поведение в духе UNIX. Формат описан спецификацией age-encryption.org/v1.
Базовый сценарий
Три команды:
$ age-keygen -o key.txt
Public key: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p
$ tar cvz ~/data | age -r age1ql3z7... > data.tar.gz.age
$ age -d -i key.txt data.tar.gz.age > data.tar.gz
Публичный ключ это одна строка с префиксом age1, приватный одна строка с префиксом AGE-SECRET-KEY-1. Никакого keyring и никакого состояния на диске кроме файла с ключом.
Что ещё умеет
Флаг -r можно повторять, тогда файл расшифрует любой из получателей. Список получателей удобнее держать файлом и передавать через -R. Флаг -p шифрует паролем, причём при пустом вводе age сгенерирует стойкую фразу сам. Флаг -a даёт текстовый PEM вывод, если файл надо вставить в письмо или в YAML. При расшифровке тип файла определяется автоматически.
Приятно, что можно шифровать на обычные SSH ключи:
$ age -R ~/.ssh/id_ed25519.pub example.jpg > example.jpg.age
$ age -d -i ~/.ssh/id_ed25519 example.jpg.age > example.jpg
Отсюда трюк с GitHub, где публичные ключи лежат по адресу вида github.com/username.keys:
$ curl https://github.com/benjojo.keys | age -R - example.jpg > example.jpg.age
С версии 1.3.0 есть гибридные постквантовые ключи через age-keygen -pq. Цена в том, что публичный ключ получателя разрастается примерно до двух тысяч символов.
Как библиотека
CLI это обёртка над пакетом filippo.io/age:
recipient, _ := age.ParseX25519Recipient(pubKey)
out := &bytes.Buffer{}
w, err := age.Encrypt(out, recipient)
if err != nil {
log.Fatal(err)
}
io.WriteString(w, "секретные данные")
w.Close() // обязателен, иначе не запишется финальный блок
Всё построено на io.Reader и io.Writer, поэтому поток по сети шифруется так же, как строка в памяти. Расшифровка через age.Decrypt с age.ParseX25519Identity.
Ставится из репозиториев почти везде, либо командой go install filippo.io/age/cmd/...@latest.
age стоит брать, когда нужно зашифровать файл и не хочется тащить модель доверия GPG. Подписей, отзыва ключей и сети доверия здесь нет и не будет. Это не замена GPG во всём, а замена в той задаче, ради которой его чаще всего и запускают.
➡️ Репозиторий
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoToProduction
⭐️ Пишем долгоживущую программу на Go с GOGC=off. Часть 1, GOMEMLIMIT
Короткий ответ: да, но не так, как обычно себе это представляют. Полностью выключенный сборщик мусора почти всегда означает, что программа рано или поздно съест всю память. Работающие варианты сводятся к тому, что GC не выключается совсем, а перестаёт запускаться по росту кучи и начинает запускаться по вашим правилам.
В этой части разберём, что делает GOGC=off, почему наивный вариант падает, и самый практичный способ жить без сборок, связку с GOMEMLIMIT.
➡️ Что делает GOGCGOGC задаёт, насколько куча должна вырасти относительно живых данных, прежде чем начнётся следующий цикл сборки. При значении по умолчанию 100 сборка стартует, когда куча удвоилась относительно объёма живых объектов после прошлого цикла. При GOGC=200 цикл будет реже и памяти уйдёт больше. При GOGC=off триггер по росту кучи пропадает совсем.
То же самое можно сделать из кода:
Важно понимать, что аллокатор при этом никуда не девается. Программа продолжает выделять память, просто освобождать её никто не будет. Каждый временный слайс, каждая строка от fmt.Sprintf, каждый заголовок HTTP запроса остаются в куче навсегда. Для батча, который живёт три секунды и завершается, это идеально. Для сервиса, который работает неделями, это утечка по определению.
➡️ Почему наивный вариант падает
Возьмём типичный HTTP сервис. Даже если ваш собственный код не аллоцирует, стандартная библиотека аллоцирует за вас. net/http создаёт объекты на каждый запрос, encoding/json создаёт их на каждый декод, драйвер базы создаёт их на каждый ряд. При тысяче запросов в секунду и паре килобайт мусора на запрос вы получаете около двух мегабайт в секунду, то есть примерно семь гигабайт в час. Дальше приходит OOM killer.
Поэтому вопрос не в том, можно ли выключить GC, а в том, чем заменить триггер, который вы выключили.
➡️ GOMEMLIMIT как замена триггера
GOMEMLIMIT — самый практичный подход и он появился в Go 1.19. Комбинация GOGC=off и GOMEMLIMIT даёт сборщик, который не реагирует на рост кучи вообще, но запускается, когда потребление памяти приближается к заданному лимиту.
Что вы получаете. Пока памяти хватает, циклов сборки нет совсем, а значит нет накладных расходов на маркировку и барьеры записи. Как только программа подходит к лимиту, GC включается и удерживает потребление около него. Куча живёт в стабильном состоянии, а не пилой от нуля до удвоения.
Что вы теряете. Если объём живых данных сам по себе дорастает до лимита, GC начнёт запускаться непрерывно и программа уйдёт в смерть от сборки, когда почти всё время уходит на бесполезные циклы. Лимит поэтому ставят с запасом относительно ожидаемого объёма живых данных, а не впритык к памяти контейнера. Разумная практика ставить GOMEMLIMIT процентов на десять ниже лимита пода, чтобы GC успел среагировать раньше, чем это сделает cgroup.
Ещё одна тонкость. GOMEMLIMIT учитывает всю память рантайма, включая стеки горутин и служебные структуры, но не учитывает то, что выделено вне рантайма, например через cgo или mmap. Если такого много, лимит надо занижать дополнительно.
➡️ Про ballast
Раньше был популярен трюк с большим фиктивным слайсом, который выделяли на старте, чтобы поднять порог срабатывания GC. Сейчас он не нужен. GOMEMLIMIT решает ту же задачу.
Итог первой частиGOGC=off сам по себе это не оптимизация, а отложенный OOM. Но GOGC=off вместе с GOMEMLIMIT вполне живёт в проде годами. Сборщик молчит на нормальной нагрузке и вступает в дело только у границы, которую вы задали сами.
Во второй части посмотрим на два более жёстких варианта. Ручные вызовы runtime.GC() в окнах простоя и код, который вообще не аллоцирует после старта.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoDeep
🔥 Стартуем СЕГОДНЯ! Новый поток курса «Разработка ИИ-агентов» открыт
По этому поводу мы решили выложить закрытую запись одного из уроков из программы. Найти её в поиске YouTube нельзя — она доступна только по ссылке и всем, кто будет на курсе.
Внутри глубокий разбор LLM от Алексея Яндутова (Senior ML-инженер, развивал ответы «Алисы» и «Нейро» в Яндексе). Учимся получать точный результат без галлюцинаций.
Что внутри урока:
- Устройство LLM.
- Рабочие шаблоны промптов (Persona, Chain-of-Thought и др.).
- Разбор реального кейса Яндекса. Как автоматизировать разметку, обойти качество людей на 5% и срезать косты на 60%.
После просмотра вы поймете, когда хватает промпт-инжиниринга, а когда нужен RAG или fine-tuning.
👉Смотреть закрытый урок на YouTubeПонравился урок? Переходите на новый уровень! Оставляйте заявку на курс, чтобы научиться проектировать надежные автономные системы. Обучение началось, но вы еще успеваете присоединиться.
🔗 Занять место на курсе
🎸 Конференция, которая заканчивается концертом
ИТ-Пикник 2026 — это не только доклады. Музыкальный хедлайнер — LAB, шоу Антона Беляева и команды Therr Maitz: популярные треки в новых аранжировках с оркестром и хором. А ещё ИТ-Квартирник — отдельная сцена для музыкантов из мира технологий, где семь команд из опен-колла борются за право выйти на главную сцену с Pompeya.
➡️ Собрали всё, что известно о фестивале
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
👀 20 ошибок, которые пропустит компилятор
Собрали в карточках ошибки, которые можно отловить на код-ревью.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoVisual
👀 20 ошибок, которые пропустит компилятор
Собрали в карточках ошибки, которые можно поймать на код-ревью.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoVisual
🚀 Уже завтра стартует новый поток курса «ИИ-агенты»!
Мы собрали мощнейший состав преподавателей. Учить вас проектировать архитектуру и собирать продакшн-агентов будут инженеры и исследователи из топовых IT-компаний.
Старт уже завтра!
Сомневаетесь, подойдет ли вам программа и подача? Начните с бесплатного демо-урока!
Всего за 2 часа вы заглянете под капот ИИ-агента, поймете, чем мышление модели отличается от ее ответа, и научите систему чинить собственный код. Это идеальный способ протестировать нашу платформу перед покупкой.
🔗 Пройти демо-урок и занять место на курсе
💬 События публикуются дважды
Сервис сохраняет заказ в БД и сразу публикует событие OrderCreated. Выглядит логично, но БД и очередь это две отдельные системы.
Что может произойти: БД коммитилась, но публикация упала. Заказ есть, события нет. Клиент повторяет запрос из за таймаута. Событие публикуется еще раз. Нижестоящий сервис видит два события и создает два заказа вместо одного.
➡️ Решение: Outbox паттерн
Сохраняем заказ и событие в одной БД транзакции. Отдельный диспетчер читает неотправленные события и публикует их позже. Если диспетчер упадет или повторится, событие уже в БД и не потеряется.
// В одной транзакции
BEGIN
INSERT INTO orders ...
INSERT INTO outbox ...
COMMIT
// Отдельно
func dispatchOutbox() {
events := store.GetUnsent()
for _, e := range events {
publisher.Send(e)
store.MarkSent(e.ID)
}
}
➡️ Ключевые моменты
Каждое событие должно иметь уникальный ID. Потребители должны быть идемпотентные (игнорировать дубликаты). Outbox паттерн гарантирует, что событие не потеряется, но не гарантирует ровно одну доставку. Это нормально, если потребители правильно обрабатывают дубликаты.
➡️ Что делать
Добавьте таблицу outbox. Вставляйте заказ и событие одной транзакцией. Запустите диспетчер, который периодически отправляет события из outbox. Добавьте уникальный event_id потребителям для фильтрации дубликатов.
Граница между микросервисами это самое опасное место. Outbox паттерн это простой способ сделать ее безопаснее.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoToProduction
⭐️ Тип в композитных литералах станет необязательнымПредложение №12854 висело в трекере с 2015 года и наконец получило статус accepted.
Теперь тип литерала можно будет опускать везде, где компилятор выводит его из контекста:
var x []string = {"a", "b", "c"}
return {}, err
compress.NewReader(r, {Level: compress.BestSpeed})
items = append(items, {id, obj, false})
Запись a := {1, 2, 3} останется ошибкой, слева нет явного типа и выводить нечего.
Выигрывают табличные тесты, структуры опций и код с protobuf, где имена типов повторяются десятками. Спор о читаемости команда закрыла так. gofmt не будет принудительно удалять типы, стиль сложится сам, а gopls получит подсказки, которые покажут пропавшее имя типа прямо в редакторе.
В Go 1.27 фича не попадёт. Изменение в компиляторе простое, но нужно обновить экосистему инструментов, поэтому ориентир это Go 1.28.
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
🛩 FlightRecorder в проде
В Go 1.25 в стандартную библиотеку завезли trace.FlightRecorder — кольцевой буфер трассировки, который постоянно крутится в памяти, а по команде Snapshot() отдаёт последние N секунд событий рантайма. Идея: сэмплирующий профайлер видит «среднюю температуру», а тут вы получаете полную картину именно того момента, когда всё пошло не так.
Пара примеров:
▪️ Ловля хвостовых задержек
Мидлварь замеряет время обработки запроса, и если оно перевалило за исторический p95 (или прилетела 500-ка) — асинхронно дёргается снапшот.
Бинарный дамп улетает в S3, ссылка логируется в Grafana. Сработал алерт → кликнули по ссылке → скачали дамп → go tool trace slow-trace.out.
▪️ Проблемы шедулера и GC
Всё, что живёт между сэмплами профайлера: залипания горутин, GC assist, вытеснение горутин с P — на трассе это видно, в профиле нет.
Но есть и обратная сторона: формат данных не дружит с Pyroscope и Datadog, поэтому дамп нельзя просто открыть в дашборде — приходится вручную гонять go tool по конкретному поду. А когда подов больше тысячи, удовольствие ниже среднего. Инструмент мощный, эргономика — пока нет.
💬 А вы пробовали FlightRecorder? Для чего включали, что нашли такого, чего не показал pprof, и как вытаскивали трейсы спрода?
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика
#GoToProduction
🔮 Прогноз для IT-рынка после 2027 года
Кажется, что рынок умер: вакансий меньше на 20-35%, зарплаты растут медленнее инфляции, hh-индекс в IT перевалил за 14. Но если наложить сегодняшний спад на три предыдущих цикла — доткомы, 2008-й и пандемию — картина выглядит иначе.
Что будет дальше: где ждать взрывного роста вакансий в 2028-2030, почему разрыв в зарплатах может достичь 50-120% и что делать в ближайшие полтора года, чтобы оказаться на правильной стороне этого разрыва.
➡️ Ответы в статье
📍 Навигация: Вакансии • Задачи • Собесы
🐸 Библиотека Go-разработчика