Forwarded from Proglib.academy | IT-курсы
Где-то есть тесты, где-то их забыли. Где-то агент следует архитектуре проекта, где-то предлагает решение, которое с ней не сочетается.
Завтра покажем, как передать AI инженерный контекст команды и не превратить его внедрение в ещё один источник хаоса.
Бесплатно. 60 минут доклада + 30 минут вопросов.
Please open Telegram to view this post
VIEW IN TELEGRAM
😁6❤2⚡1🤔1🥱1
Раньше
go fix вспоминали редко. Команда осталась со времён Go 1.0, когда язык менялся часто и код приходилось подтягивать под новые правила. После обещания об обратной совместимости нужда в ней почти отпала, и многие о ней просто забыли. В Go 1.26 её переписали заново, и теперь это инструмент модернизации кода, а не реликт.Как запускать
Команда принимает шаблоны пакетов, как
go build и go vet. Правка всех пакетов ниже текущей директории:go fix ./...
При успехе файлы меняются молча. Правки в сгенерированных файлах команда пропускает, потому что чинить нужно генератор, а не результат. Запускайте из чистого git-состояния, тогда в диффе будут только изменения от
go fix, и ревьюеру будет проще.Посмотреть правки заранее, ничего не меняя, помогает флаг
-diff:go fix -diff ./...
Список доступных анализаторов выводит отдельная команда:
go tool fix help
Можно запросить документацию по конкретному анализатору:
go tool fix help forvar
По умолчанию запускаются все анализаторы. На большом проекте удобнее применять правки по одному анализатору за раз, чтобы ревью не превращалось в кашу. Включить только нужный можно флагом с его именем, например
-any. Наоборот, выключить один и оставить остальные помогает форма -any=false.Правки под новые возможности применяются только в тех файлах, где версия Go достаточно свежая. Ориентир берётся из директивы
go в go.mod или из build-тега вроде //go:build go1.26. Так инструмент не тащит фичи туда, где они ещё не поддерживаются.Пара нюансов
Одна правка иногда открывает дорогу другой. Например,
minmax сначала подставит max, а на втором проходе увидит и min. Поэтому имеет смысл прогнать команду дважды, обычно этого хватает.Изредка встречаются семантические конфликты, когда две независимые правки вместе оставляют неиспользуемую переменную, а это ошибка компиляции в Go. Такие случаи обычно всплывают сразу при сборке, но требуют ручной доработки. Неиспользуемые импорты
go fix при этом убирает сам отдельным проходом.Мы получили команду, которую есть смысл запускать регулярно, а не раз в пятилетку. Хороший момент — сразу после апгрейда тулчейна. Обновите проект до Go 1.26, запустите
go fix ./... из чистого git-состояния и посмотрите на дифф. Заодно можно подтянуть свежие идиомы языка, которые иначе легко пропустить.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍13❤7🔥1👏1🎉1
Когда в приложении на Go с GORM появляется поиск по тексту, первым в код обычно попадает
LIKE '%слово%'. На небольшой таблице это терпимо. Дальше начинаются проблемы. Запрос сканирует всю таблицу, не понимает словоформы, чувствителен к регистру, а обычный индекс ему не помогает. В PostgreSQL для таких задач есть встроенный полнотекстовый поиск на
tsvector и tsquery. GORM с ним работает без отдельных библиотек, потому что нужные операторы можно передать внутрь .Where().Как это устроено
Тип
tsvector — это нормализованный набор лексем из текста. Функция to_tsvector приводит слова к основе и выкидывает стоп-слова, поэтому запрос по слову running находит документ со словом run. Тип tsquery описывает сам поисковый запрос. Функция
plainto_tsquery берёт строку от пользователя и превращает её в запрос, безопасно игнорируя спецсимволы вроде & и |. Оператор @@ проверяет, совпадает ли вектор с запросом, и возвращает булево значение.Базовый вариант
Проще всего собрать условие прямо в
.Where(). Модель и функция поиска выглядят так:package main
import (
"gorm.io/driver/postgres"
"gorm.io/gorm"
)
type Product struct {
ID uint `gorm:"primaryKey"`
Title string
Description string
}
func SearchProducts(db *gorm.DB, term string) ([]Product, error) {
var products []Product
err := db.Where(
"to_tsvector('english', title || ' ' || description) @@ plainto_tsquery('english', ?)",
term,
).Find(&products).Error
return products, err
}
Здесь
title и description склеиваются в один вектор, а ввод пользователя уходит параметром через ?, так что про SQL-инъекции можно не беспокоиться. Минус подхода в том, что вектор считается заново для каждой строки в момент запроса. Индекс тут не используется, и на большой таблице это становится медленно.Быстрый вариант с отдельным столбцом и GIN-индексом
Чтобы не пересчитывать вектор на лету, его хранят в отдельном столбце и ускоряют индексом типа GIN. Столбец удобно сделать генерируемым, тогда PostgreSQL сам поддерживает его в актуальном состоянии при любой вставке или обновлении.
В модели этот столбец помечается как доступный только для чтения. Тег
-> говорит GORM не пытаться писать в него, ведь значение вычисляет база:type Book struct {
ID uint `gorm:"primaryKey"`
Title string
Description string
SearchVector string `gorm:"->;type:tsvector"`
}Сам генерируемый столбец и индекс создаются сырым SQL после
AutoMigrate, потому что синтаксис генерируемых столбцов GORM через теги не выразит:func InitDatabase(db *gorm.DB) {
db.AutoMigrate(&Book{})
db.Exec(`
ALTER TABLE books
ADD COLUMN IF NOT EXISTS search_vector tsvector
GENERATED ALWAYS AS (
to_tsvector('english', coalesce(title, '')) ||
to_tsvector('english', coalesce(description, ''))
) STORED;
`)
db.Exec(`
CREATE INDEX IF NOT EXISTS idx_books_search_vector
ON books USING gin(search_vector);
`)
}Запрос теперь обращается к готовому столбцу, поэтому нагрузка не растёт вместе с размером таблицы:
func FastSearch(db *gorm.DB, term string) ([]Book, error) {
var results []Book
err := db.Where("search_vector @@ websearch_to_tsquery('english', ?)", term).
Find(&results).Error
return results, err
}Здесь вместо
plainto_tsquery стоит websearch_to_tsquery. Он понимает привычный по поисковикам синтаксис. Кавычки задают точную фразу, а минус перед словом исключает его из выдачи. Для строки поиска от пользователя это обычно удобнее.Что выбрать
Для прототипа или небольшой таблицы хватит базового варианта через
to_tsvector прямо в .Where(). Как только объём данных растёт и поиск начинает тормозить, переходите на генерируемый столбец с GIN-индексом. Логика запроса при этом почти не меняется, а скорость перестаёт зависеть от размера таблицы.📍 Навигация: Вакансии • Задачи • Собесы
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7❤4👍1😁1
Оптимизировать Go есть смысл, когда приложение упирается в CPU, память или задержки в проде. И только после того, как вы замерили, где именно медленно, а не по ощущениям.
Собрали пять техник, которые убирают лишние аллокации и системные вызовы. Преаллокация слайсов,
strings.Builder, аккуратная работа с []byte, буферы для I/O и выравнивание полей в структурах.📍 Навигация: Вакансии • Задачи • Собесы
#GoVisual
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥8👍7❤4
Please open Telegram to view this post
VIEW IN TELEGRAM
Forwarded from Proglib.academy | IT-курсы
Агент работает только с тем контекстом, который ему дали. Если документация неполная или устарела, он начинает додумывать — отсюда появляется неверный код.
Также разберём, как выбирать модель под задачу: Claude, DeepSeek, Qwen и другие
Впереди 7 недель работы со своим репозиторием. Вебинары проходят вживую и остаются в записи.
Стартуем 31 августа. До конца июля можно присоединиться по ранней цене, а доступ к материалам останется бессрочным
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2😁2👍1🤔1
Go легче учить на реальных задачах, но придумать задачу порой сложнее, чем решить. Собрали идеи по уровням, каждую можно закрыть за вечер.
Для старта
• Утилита командной строки. Го собирается в один бинарник, раздавать удобно.
• Поиск дубликатов файлов по хешу, свой аналог
grep, конвертер csv в json. Освоите флаги, чтение из потока и работу с файлами.Конкурентность
• Чекер доступности сайтов опрашивает адреса параллельно, десять штук проверяются за время самого медленного ответа.
• Пул воркеров покажет, зачем каналы и как ограничивать нагрузку.
• Кэш с временем жизни объяснит, почему доступ к карте без блокировки ломает программу.
Сеть и сервисы
• Сокращатель ссылок закроет тему HTTP сервиса и роутинга.
• Прокси научит перехватывать трафик.
• Телеграм бот даст практику с внешним API и вебхуками.
Ближе к продакшену
• База ключ значение с журналом на диске покажет как организовать долговечность данных.
• Rate limiter познакомит с токен бакетом.
• Сборщик метрик научит работать с системными вызовами.
Берите задачу, которая пригодится вам самим. Начните с утилиты и усложняйте.
📍 Навигация: Вакансии • Задачи • Собесы
#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
❤7👍6😢1
Куда на самом деле уходят токены во время агентного кодинга? ⚡️
Forwarded from Proglib.academy | IT-курсы
В итоге станет понятнее, сколько ресурсов выделять на запуск, когда его останавливать и в какой момент лучше изменить подход🔍
До 31 июля курс можно купить со скидкой, а все материалы останутся в бессрочном доступе.
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱10🤔1🤩1
В трекере Go появилось предложение #78902 о переносимом SIMD API. Автор — David Chase из команды компилятора. Это второй уровень поверх той работы над SIMD, что описана в проекте #73787. Важно сразу оговорить статус. Это предложение в состоянии Active, оно ещё обсуждается и не принято.
Напомним контекст. В Go 1.26 уже появился экспериментальный пакет
simd/archsimd, который включается через GOEXPERIMENT=simd. Он даёт доступ к SIMD-инструкциям конкретной архитектуры, то есть вы работаете напрямую с типами вроде Float32x8 и должны сами учитывать, что доступно на целевом процессоре. Новое предложение решает другую боль. Писать под каждую архитектуру и под каждую ширину вектора отдельно неудобно, а код получается непереносимым.Идея в том, чтобы дать абстрактный интерфейс к SIMD-векторам, не завязанный ни на архитектуру, ни на длину вектора. Там, где инструкции есть, API работает быстро. Там, где их нет, он сохраняет переносимость за счёт эмуляции. При запуске на разных вариантах одной архитектуры библиотека сама выбирает лучший доступный набор, например переключается между AVX, AVX2 и AVX512.
В первой версии список операций небольшой. Это пересечение SIMD API для wasm и текущего amd64. Набор скромный, зато его проще эмулировать на платформах без SIMD и проще поддержать при добавлении новых архитектур. Типы названы по образцу заглавной буквы и множественного числа, например
Int8s или Float64s. Внутри одного запуска программы все векторы имеют одинаковую длину в битах, поэтому их можно переинтерпретировать методами вида
x.AsFloat64s(). Маски вынесены в отдельную абстракцию, потому что архитектуры реализуют их по-разному. У типов есть методы .Masked(mask) и .Merged(valueIfFalse, mask), а сами маски комбинируются через And и Or.Предусмотрен и спуск на уровень конкретной архитектуры через
ToArch() и обратно через ToSimd(), хотя в прототипе этого пока нет. По задумке это выглядит так://go:build amd64
import (
"simd"
"simd/archsimd"
)
func sum(x simd.Float32s) float32 {
switch a := x.ToArch().(type) {
case archsimd.Float32x8:
a = a.AddPairsGrouped(a)
a = a.AddPairsGrouped(a)
return a.GetLo().GetElem(0) + a.GetHi().GetElem(0)
case archsimd.Float32x16:
// ...
case archsimd.Float32x4:
// ...
}
}
Под капотом код, зависящий от пакета
simd, компилятор размножает на несколько вариантов под разные наборы инструкций, а функции со скрытой зависимостью превращает в диспетчеры. Переписывание идёт рано, чтобы сохранить шанс на инлайнинг. Есть нюанс для инструментов. Сгенерированные имена содержат символ
@ и недоступны из исходного кода, что может влиять на отладчики и утилиты, читающие символы объектных файлов.Есть черновой CL 763100, где сам API лежит в
simd/mocks.go и генерируется автоматически. Пробовать в проде рано, но за направлением стоит следить, если вам важна производительность на горячих циклах.📍 Навигация: Вакансии • Задачи • Собесы
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10❤2👏1💯1
⚡️ Highload на Go: System Design, Kubernetes и микросервисы под нагрузкой — новый курс на Mentorix
Highload глазами Go-инженера: как проектировать, писать и эксплуатировать сервисы, которые держат нагрузку. С расчётами и симуляциями, как на реальных собеседованиях.
⚙️ Внутри: перцентили и SLO, конкурентность и профилирование, кэширование, rate limiting, ретраи и circuit breaker, очереди, БД под нагрузкой, Kubernetes, system design
🧩 118 задач с автопроверкой — вся практика на Go
🎓 Сертификат · доступ навсегда
▶️ Часть уроков открыта — начать можно бесплатно
🏷 −50% — скидка действует 24 часа
19 990 ₽ → 9 995 ₽
➜ Забрать курс со скидкой
━━━━━━━━━━━━━━
Курс продвинутый — предполагает уверенный Go. Если хотите подтянуть базу, на платформе есть бесплатные курсы:
🧩 Тренажёр Go — 70 задач с автопроверкой
⚡️ Golang — основы языка
Сети для разработчиков: TCP/IP, HTTP, DNS
📚 Все бесплатные курсы Mentorix
Highload глазами Go-инженера: как проектировать, писать и эксплуатировать сервисы, которые держат нагрузку. С расчётами и симуляциями, как на реальных собеседованиях.
⚙️ Внутри: перцентили и SLO, конкурентность и профилирование, кэширование, rate limiting, ретраи и circuit breaker, очереди, БД под нагрузкой, Kubernetes, system design
🧩 118 задач с автопроверкой — вся практика на Go
🎓 Сертификат · доступ навсегда
▶️ Часть уроков открыта — начать можно бесплатно
🏷 −50% — скидка действует 24 часа
➜ Забрать курс со скидкой
━━━━━━━━━━━━━━
Курс продвинутый — предполагает уверенный Go. Если хотите подтянуть базу, на платформе есть бесплатные курсы:
🧩 Тренажёр Go — 70 задач с автопроверкой
⚡️ Golang — основы языка
Сети для разработчиков: TCP/IP, HTTP, DNS
📚 Все бесплатные курсы Mentorix
❤2
Вопрос с ловушкой прямо в формулировке — и на ней спотыкается половина кандидатов.
Подсказка: прежде чем называть примитив, спросите — а что именно ограничиваем? «Не больше 10 одновременно» и «не больше 100 в секунду» — две разные задачи с разными инструментами. Перепутаете — ответите не на тот вопрос.
Дальше просто: для «одновременно» есть классический примитив, который в Go делается на одном канале особого типа (почему именно такого — тоже любят спросить). А в проде берут готовую обёртку из
golang.org/x/... — тот же механизм, но с ошибками, Wait и отменой через контекст.chan struct{} и что за обёртка — полный разбор📍 Навигация: Вакансии • Задачи • Собесы
#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
❤1