Библиотека Go-разработчика | Golang
23.4K subscribers
2.26K photos
47 videos
87 files
4.66K links
Все самое полезное для Go-разработчика в одном канале.

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

Учиться у нас: https://proglib.io/w/32d20779

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

РКН: https://gosuslugi.ru/snet/67a4a8c2468
Download Telegram
⚡️ Как не убить производительность работой со строками

Работа со строками в Go может незаметно съесть всю память и убить производительность. Разбираем, как избежать ненужных аллокаций и ускорить код в разы.

В Go строки неизменяемые. Каждое изменение строки = новая аллокация в памяти.

Пример проблемного кода:
func BuildURL(host, path, query string) string {
url := "https://" // Аллокация #1
url += host // Аллокация #2
url += path // Аллокация #3
url += "?" + query // Аллокация #4
return url
}


Решение 1: strings.Builder с предвыделением

Всегда используйте strings.Builder вместо конкатенации через +:
// N аллокаций
func ConcatWrong(parts []string) string {
result := ""
for _, p := range parts {
result += p // Новая аллокация на каждой итерации!
}
return result
}

// 1 аллокация
func ConcatRight(parts []string) string {
var b strings.Builder

// Посчитать нужный размер заранее
totalLen := 0
for _, p := range parts {
totalLen += len(p)
}
b.Grow(totalLen) // Выделить память один раз

// Писать без аллокаций
for _, p := range parts {
b.WriteString(p)
}
return b.String()
}


Решение 2: Переиспользование буферов через sync.Pool

Даже strings.Builder делает аллокацию при вызове .String(). Чтобы избежать этого, переиспользуйте буферы:
var bufferPool = sync.Pool{
New: func() interface{} {
b := make([]byte, 0, 4096) // 4KB буфер
return &b
},
}

func GetBuffer() *[]byte {
return bufferPool.Get().(*[]byte)
}

func PutBuffer(b *[]byte) {
*b = (*b)[:0] // Сбросить длину, сохранить capacity
bufferPool.Put(b)
}

func BuildString(parts []string) string {
buf := GetBuffer()
defer PutBuffer(buf)

for _, p := range parts {
*buf = append(*buf, p...)
}

// Zero-copy конвертация (Go 1.20+)
return unsafe.String(unsafe.SliceData(*buf), len(*buf))
}


Решение 3: Стековые массивы для предсказуемых размеров

Для строк фиксированного размера используйте массивы на стеке:
// heap allocation
func FormatIPWrong(a, b, c, d byte) string {
return fmt.Sprintf("%d.%d.%d.%d", a, b, c, d)
}

// stack allocation
func FormatIPRight(a, b, c, d byte) string {
var buf [15]byte // Макс длина IP: "255.255.255.255"
i := 0

i += writeUint8(buf[i:], a)
buf[i] = '.'
i++
i += writeUint8(buf[i:], b)
buf[i] = '.'
i++
i += writeUint8(buf[i:], c)
buf[i] = '.'
i++
i += writeUint8(buf[i:], d)

return string(buf[:i])
}

func writeUint8(buf []byte, v byte) int {
if v >= 100 {
buf[0] = '0' + v/100
buf[1] = '0' + (v/10)%10
buf[2] = '0' + v%10
return 3
} else if v >= 10 {
buf[0] = '0' + v/10
buf[1] = '0' + v%10
return 2
}
buf[0] = '0' + v
return 1
}


Решение 4: String Interning для дедупликации

Если у вас много одинаковых строк (например, в логах), используйте string interning:
type Interner struct {
mu sync.RWMutex
pool map[string]string
}

func (i *Interner) Intern(s string) string {
i.mu.RLock()
if cached, ok := i.pool[s]; ok {
i.mu.RUnlock()
return cached
}
i.mu.RUnlock()

i.mu.Lock()
defer i.mu.Unlock()

if cached, ok := i.pool[s]; ok {
return cached
}

i.pool[s] = s
return s
}

// Использование
var logLevelInterner = NewInterner()

func ProcessLog(level string) {
level = logLevelInterner.Intern(level)
// Теперь все "info" указывают на одну строку в памяти
}


Как профилировать:
# Посмотреть аллокации памяти
go test -bench=. -benchmem

# Проверить escape analysis
go build -gcflags="-m" 2>&1 | grep "string"

# Memory profiling
go test -bench=. -memprofile=mem.prof
go tool pprof -alloc_space mem.prof


Главное правило: всегда измеряйте! Не доверяйте интуиции — используйте бенчмарки.

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍294🌚1
✏️ LeetCode-интервью: почему опытные разработчики их проваливают

Инженер с 10+ годами опыта провалил интервью, потому что не смог за 45 минут решить задачу на динамическое программирование, которую не видел с универа.

Есть аргументы за решение задач не собеседовании и против.

Никто не будет решать задачки с литкода на работе, но и код с O(n²) вместо O(n log n) сто процентов положит прод под нагрузкой.

Админ один раз перенервничал и забыл как найти середину отрезка на плоскости. Это полностью заруинило ему алгоритмическую секцию.

💬 Как вы думаете — задачи на собесе это ту мач или имеют место быть? Ждём ваше мнение в комментариях 👇

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
4
⭐️ Дайджест недели

С вами библиотека Go-разработчика и мы освежаем в памяти прошедшую неделю.

Черновик про релиз Go 1.26

Контекстные сетевые функции, классификация переменных в go/types, кастомизация сканирования БД и полная поддержка Windows file flags

Подборка курсов для повышения скиллов

14 вопросов, после которых вам не перезвонят

Свежий Cup o' Go

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
Что такое неэкспортируемая пустая структура

Это структура, определённая как struct{}, без полей и с именем, начинающимся со строчной буквы, чтобы ограничить область видимости внутри пакета.

Зачем она нужна

• Неэкспортируемую пустую структуру часто используют, чтобы обозначить, что тип реализует определённый интерфейс, или для добавления семантики без хранения состояния.

• Так как struct{} занимает 0 байт, её используют в ситуациях, где нужно просто присутствие элемента без данных:
set := map[string]struct{}{}
set["apple"] = struct{}{}


• Пустая структура идеальна для каналов, передающих только сигнал, а не данные:
done := make(chan struct{})
go func() {
// работа
done <- struct{}{}
}()
<-done


• Если структура неэкспортируема, она не видна за пределами пакета — удобно для инкапсуляции логики, когда внешний код должен работать только через интерфейсы.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍114🥱2
🧠 Готовишься к собесам, а ноутбук еле тянет IDE?

Самое время прокачать скиллы и апгрейднуть железо!

Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻

Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!

📚 Среди курсов:

▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.

▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.

▫️ Python, математика для DS, основы IT и другие направления.

👉 Принять участие
🥱81
⚡️ Реверс-прокси с балансировкой

Между «накинуть Nginx с парой строк конфига» и «развернуть HAProxy с мониторингом» есть промежуточный вариант. Traffic Balancer — это Go-библиотека с балансировкой, health checks и защитой от перегрузов.

Библиотека предлагает четыре стратегии распределения запросов:

• least-time — анализирует среднюю задержку каждого сервера и отправляет запрос туда, где она ниже. Полезно, когда у серверов разная производительность.

• weighted-round-robin — распределяет нагрузку по весам. Задаёте в конфиге weight: 0.1 и 0.9, и более мощный сервер получит в 9 раз больше запросов.

• connection-per-time — следит за количеством соединений на каждом сервере. Если за минуту превышен лимит из конфига, сервер временно выключается из ротации.

• round-robin — классика. Запросы идут по очереди: первый на сервер А, второй на Б, третий снова на А.

Пример конфига:
# least-time
# weighted-round-robin
# connection-per-time
# round-robin
algorithm: "weighted-round-robin" # Algorithm to be used
port: 3030 # Port that the reverse proxy will run on
strict: true # Strict mode for black-listing IPs
log: true # Save logs to file in log folder
access-control-allow-origin: "*" # CORS HEADERS
max-body-size: 1024 # Maximum body size!
xss-protection: true # In default true it will add xss protection header to the requested sent from load balancer to the server.
servers: #List of servers.
-
host: "https://localhost:9876"
weight: 0.1
connections: 1

-
host: "https://localhost"
weight: 0.9
connections: 100


Запуск:
go build
./traffic-balancer


Всё. Балансировщик поднимается на указанном порту и начинает работу.

➡️ Репозиторий либы

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥10
🧑‍💻 Подготовка к 6-дневке: инструкция для взрослых

Шаг 1: Осознать, что выбора нет
Шаг 2: Смириться
Шаг 3: ???
Шаг 4: PROFIT

💬 А вы готовы? Как проходит второй понедельник? Или у вас будет две пятницы?

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
😁72
✏️ Интерфейс потребитель, а не производитель

Одна из классических ошибок начинающих Go-разработчиков — определять интерфейсы слишком рано и слишком широко. Интерфейс должен описывать поведение, которое вам нужно, а не всё, что умеет делать структура.

Плохо:
type Database interface {
Create()
Read()
Update()
Delete()
}


Здесь мы создали толстый интерфейс со всеми возможными операциями. Но что если вашему коду нужно только читать данные?

Хорошо:
type Reader interface {
Read() ([]byte, error)
}


Узкий интерфейс, описывающий ровно то, что нужно конкретному потребителю.

Думайте как потребитель: «Что мне нужно от этой зависимости?» — и определяйте интерфейс исходя из ответа. Это чистый YAGNI для интерфейсов — не определяй методы, пока они не нужны.

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍191🌚1
🎁 Конкурс от Proglib Academy!

Кстати, если кто-то ещё не в курсе — у нас тут раздают MacBook Pro 14.
Да-да, не шутка, настоящий, железный, с M3 Pro

Но! Чтобы успеть пройти 2 недели обучения к 15 ноября, курс нужно взять до конца октября — и сейчас на всё скидка 40%.

Чтобы поучаствовать, нужно:

1️⃣ Покупаешь любой курс до конца октября;
2️⃣ Проходишь 2 недели обучения к 15 ноября;
3️⃣ Написать куратору в чат #розыгрыш.

До 15 ноября, потом всё — поезд (и макбук) уйдёт.

👉 Участвовать в розыгрыше
🥱1
✏️ Разбираем битовую задачку

Сегодня в ежедневной задаче на литкоде попалась интересная штука — нужно найти наименьшее число, которое не меньше заданного N и состоит только из единиц в двоичной записи.

Вам дают число, например, 10 (в двоичной системе это 1010). Нужно найти ближайшее число >= 10, где все биты — единицы. В данном случае это 15 (двоичная 1111).

Первое решение, которое приходит в голову. Можно просто пройтись по всем битам исходного числа и установить каждый в 1:
func smallestNumber(n int) int {
result := 0
bitPosition := 0

for n > 0 {
result |= (1 << bitPosition) // устанавливаем бит
bitPosition++
n >>= 1 // сдвигаем к следующему биту
}

return result
}


Работает, но есть способ элегантнее. Решение в одну строчку:

Вспомните, как выглядят числа-степени двойки минус один:

2¹ - 1 = 1 (двоичная: 1)
2² - 1 = 3 (двоичная: 11)
2³ - 1 = 7 (двоичная: 111)
2⁴ - 1 = 15 (двоичная: 1111)

Видите паттерн? Нам нужно найти самый старший бит в исходном числе и взять следующую степень двойки минус один.

Для числа 10 (двоичная 1010) старший бит на позиции 3. Значит, берём 2⁴ - 1 = 15.
func smallestNumber(n int) int {
x := 1
for x - 1 < n {
x <<= 1 // умножаем на 2
}
return x - 1
}


Или через битовые операции с помощью bits.Len:
import "math/bits"

func smallestNumber(n int) int {
bitLength := bits.Len(uint(n)) // находим количество бит
return (1 << bitLength) - 1
}


Число с N единицами подряд — это всегда 2^N - 1. Мы находим, сколько битов нужно, чтобы вместить наше число, и берём число с таким количеством единиц.

➡️ Решить задачу

Чтобы щёлкать такие задачи не нужно знать, всё, хватит базы. Подтянуть такую базу поможет наш курс по алгоритмам. До конца октября скидка 40%

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

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍863👏2
🚀 Хотите прокачать навыки DevSecOps и безопасно управлять инфраструктурой и кодом? Приглашаем на два открытых вебинара в рамках курса «Внедрение и работа в DevSecOps»!

🗓 13 ноября, 20:00 - «Безопасность k8s: актёры и роли»:
- Разбираем RBAC в Kubernetes: субъекты, роли и биндинги
- Принцип наименьших привилегий и проектирование минимальных разрешений
- Примеры настройки ролей для команд и сервис-аккаунтов

🎯 Для DevOps, SRE, администраторов Kubernetes и ИБ-инженеров.

🗓 20 ноября, 20:00 - «SAST, их много, почему столько, а сколько нужно нам? А главное, какие?»:
- Чем различаются инструменты SAST и для каких кейсов подходят
- Как выбрать подходящие инструменты и комбинировать их без лишних накладных расходов
- Что делать с негативными особенностями работы SAST

🎯 Для архитекторов, разработчиков, DevOps, DevSecOps и AppSec-специалистов.

⚡️ Не упустите шанс бесплатно ознакомиться с практикой DevSecOps! Регистрация открыта: https://clc.to/r-2I0g

Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
1
🤨 На одну вакансию теперь 2383 отклика

Вакансий для программистов стало на 17% меньше, резюме — на 25% больше. Рынок изменился: теперь это не «рынок кандидата», а «рынок работодателя».

В статье про то, что происходит с зарплатами, какие специалисты сейчас наиболее востребованы и почему одного знания языка уже недостаточно

➡️ Узнать как там рынок

🐸 Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱3😁2
♣️ Крупнейшие LLM сражаются в покерном турнире

Пока мы спорим, нужен ли в Go дженерик или if err != nil — это фича, крупнейшие языковые модели режутся в покер на деньги.

Каждая модель получает одинаковый промпт и играет без внешних инструментов — только чистая логика и матожидание. Можно в реальном времени смотреть, как Claude решает, стоит ли идти all-in с парой двоек, а GPT пытается вычислить блеф у Gemini.

➡️ Понаблюдать за нейросетями

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
😁11👍2
This media is not supported in your browser
VIEW IN TELEGRAM
Как вырасти в тимлида за 4 года? Слушаем мнение Егора Гартмана, технического руководителя команды в вертикали Недвижимость в Авито

Он прошёл этот путь самостоятельно и теперь стал новым гостем «AviTalk» — это шоу о сотрудниках Авито, их интересах, целях в работе и вне её. Вместе с ведущим Виктором Раевым они обсудили:

как выглядят команды внутри Авито и как различается их функционал?
как меняется жизнь, когда ты теперь тимлид?
как проводить собеседования и качать софт-скиллы?
и как расслабляться, покоряя снежные вершины?

📺Смотрим по ссылке!
Please open Telegram to view this post
VIEW IN TELEGRAM
2👏1🥱1
📎 Новый экспериментальный сборщик мусора в Go

Go 1.25 представил новую экспериментальную версию сборщика мусора под названием Green Tea, которая уже доступна для тестирования и активно используется внутри Google.

Основная цель Green Tea — снизить нагрузку на CPU, связанную с работой сборщика мусора.

Green Tea предлагает принципиально новый подход к алгоритму mark-sweep, который лежит в основе сборки мусора в Go. Вместо того чтобы сканировать объекты по отдельности, Green Tea работает с целыми страницами памяти.

Однако, как и любой экспериментальный компонент, Green Tea не всегда даёт прирост производительности.

В некоторых случаях, когда структура кучи не позволяет эффективно накапливать объекты на странице, результаты могут быть хуже, чем у классического сборщика.

Тем не менее, для большинства рабочих нагрузок новая реализация показывает значительное улучшение.

➡️ Подробнее об этом в блоге Go разработчиков

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
15👍2
🎃 Хэллоуин в Proglib Academy: скидки, призы и... немного паники

Сегодня 31 октября, и это не просто время тыкв и призраков, это ПОСЛЕДНИЙ ДЕНЬ, когда ты можешь выиграть макбук!

→ Купи любой курс со скидкой 40% 💸
→ Начни обучение, чтобы пройти 2 недели к 15 ноября 🎓
→ Напиши куратору #розыгрыш ✍️

Всё! Теперь ты в игре.

👉 Сейчас или никогда!
1🥱1