Библиотека Go-разработчика | Golang
23.9K subscribers
2.74K photos
50 videos
88 files
5.37K links
Все самое полезное для Go-разработчика в одном канале.

Учиться у нас: clc.to/qaSdww

По рекламе: @proglib_adv

Для обратной связи: @proglibrary_feeedback_bot

РКН: https://gosuslugi.ru/snet/67a4a8c24689c2151c752af0

#WXSSA
Download Telegram
✏️ Если вы уже работаете с Claude Code, Cursor или Copilot, этот вебинар будет особенно полезен.

Разберут, как превратить AI из инструмента для отдельных задач в часть инженерного процесса ⬇️
Please open Telegram to view this post
VIEW IN TELEGRAM
😸 Каждый разработчик подходит к задаче со своим опытом: помнит прошлые решения, знает ограничения проекта и понимает, какой код команда пропустит на ревью.

Для человека это естественная часть работы. У Claude Code этого контекста по умолчанию нет — только задача и инструкции, которые ему дали.

Поэтому в большой команде недостаточно просто выбрать хорошую модель.

❗️ Нужно ещё объяснить ей, как у вас устроена разработка: какие подходы приняты, что обязательно проверять и по каким правилам принимать решения.


🗓 23 июля в 19:00 МСК поговорим об этом на бесплатном вебинаре с Алексеем Жиряковым — он Executive Director в Сбере, руководит
GenAI Data Platform, и с этой проблемой сталкивался не раз 🔥

Покажет живое демо, разберём, как встроить AI в процесс разработки так, чтобы он реально помогал, а не добавлял ещё один повод для споров на ревью.

🔗 Занять место на вебинаре

🏃‍♀️ Proglib Academy
Please open Telegram to view this post
VIEW IN TELEGRAM
📎 Общие неэкспортируемые функции в Go

В пакете несколько файлов, и всем нужна одна неэкспортируемая функция. Куда её положить.

Файлы внутри пакета не важны

Область видимости в Go это пакет, а не файл. Все файлы с одним package foo в одной директории видят функции друг друга, включая приватные. Значит объявляйте общую функцию в любом файле, остальные её увидят без импортов и дублей. Хелперы обычно кладут в файл по смыслу, например parse.go. Свалку utils.go заводить не стоит, держите функции рядом с их сущностью.

Если функция нужна нескольким пакетам

Когда приватную логику переиспользуют два и более пакета модуля, используйте internal:
internal/hashing/hashing.go  // общий код
api/api.go // импортирует internal/hashing


Пакет в директории internal импортируют только пакеты из того же поддерева. Функция экспортируется внутри internal/hashing, но снаружи модуля пакет закрыт.

📍 Навигация: ВакансииЗадачиСобесы

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍82🤔1
This media is not supported in your browser
VIEW IN TELEGRAM
AvitoTech Go&Grill в СПб уже ЗАВТРА 🔥

22 июля AvitoTech собирает Go-разработчиков на свой фирменный и максимально кайфовый формат Go&Grill. Ивент будет в баре «Юнион». В программе никакой корпоративной духоты:

— Fast food System Design — в командах соберёте архитектуру для мемного проекта;
— Go-бинго;
— зона для отдыха, бар и, конечно, вкусная еда с гриля!

Ждут Go-разработчиков и тех, кто хочет перейти в Go из другого бэкенд-стрима.

Скорее регистрируйтесь, ссылка еще активна! 🤓
Please open Telegram to view this post
VIEW IN TELEGRAM
🌐 Движок блога на Go держит 150 RPS на 1/8 ядра

Разработчик Мика Уэйд захостил блог на самом слабом бесплатном Oracle VPS. Это 1/8 ядра CPU и 1 ГБ памяти. Чтобы выжать из такого железа максимум, он написал собственный движок на Go. Ниже про то, почему выбрал Go и что показали замеры.

Почему не Python и не Hugo

Автор пишет на Python, поэтому первым делом думал про FastAPI или чистый Python. Но на таком тесном сервере критична каждая крупица производительности, а Python по накладным расходам здесь проигрывает. Hugo отмёл из за опасений по памяти.

В итоге выбор пал на Go, хотя раньше автор на нём не писал. Решающим стало то, как Go и Python по разному управляют памятью.

У Go компактный рантайм и сборщик мусора, который не раздувает потребление на простых нагрузках. Движок собран с нуля. Посты пишутся в Markdown и конвертируются в HTML, примерно как в Hugo.

➡️ Память

Голый минимальный Ubuntu с SSH занимал 179 Mi. После запуска приложения через bash скрипт потребление стало даже меньше, 155 Mi. Сам движок настолько лёгкий, что без нагрузки его вклад почти незаметен.

➡️ Нагрузочный тест

Автор прогнал трафик от 1 до 1000 RPS, по 60 секунд на ступень, около 4% запросов поисковые.
По задержке до 150 RPS ответ стабильно держится около 53 мс. На 300 RPS растёт, но остаётся здоровым. Выше сервер упирается в потолок и начинаются таймауты.

По CPU до 150 RPS движок ест меньше 20% одного ядра из двух доступных. Насыщение наступает между 300 и 500 RPS.

По памяти самое интересное. Потребление держится ровно на 18–19 МБ при низкой и средней нагрузке. Только на 1000 RPS поднимается примерно до 34 МБ с пиками около 50–60 МБ. Для веб приложения под нагрузкой это очень скромно, и здесь как раз виден компактный рантайм Go.

Связка минимального Ubuntu и движка на Go дала стабильные 53 мс и около 18 МБ памяти вплоть до 150 RPS. Хороший аргумент в пользу Go там, где ресурсов почти нет.

➡️ Блог разработчика

📍 Навигация: ВакансииЗадачиСобесы

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍18😁31
🔒 Скорость разработки растёт, но вместе с ней появляется новая проблема — кодовая база быстро теряет единый стиль.

Ниже — бесплатный вебинар о том, как этого избежать ⚠️
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🤢 Чем больше разработчиков в команде начинают пользоваться Claude Code, тем заметнее одна проблема: кодовая база перестаёт выглядеть как работа одной команды.

Где-то есть тесты, где-то их забыли. Где-то агент следует архитектуре проекта, где-то предлагает решение, которое с ней не сочетается.

⚠️ И это не проблема Claude Code. Он просто следует тому контексту, который получает от каждого разработчика.

Завтра покажем, как передать AI инженерный контекст команды и не превратить его внедрение в ещё один источник хаоса.

🗓 23 июля, 19:00 МСК
Бесплатно. 60 минут доклада + 30 минут вопросов.

🔗 Занять место на вебинаре и разобраться, почему так происходит

🏃‍♀️ Proglib Academy
Please open Telegram to view this post
VIEW IN TELEGRAM
😁511🥱1
⚙️ go fix в Go 1.26 из музейного экспоната стал рабочим инструментом

Раньше 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-состояния и посмотрите на дифф. Заодно можно подтянуть свежие идиомы языка, которые иначе легко пропустить.

📍 Навигация: ВакансииЗадачиСобесы

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍124
🧑‍💻 Полнотекстовый поиск PostgreSQL через GORM

Когда в приложении на 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-индексом. Логика запроса при этом почти не меняется, а скорость перестаёт зависеть от размера таблицы.

📍 Навигация: ВакансииЗадачиСобесы

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥62