Please open Telegram to view this post
VIEW IN TELEGRAM
😁26👍4❤3
🎧 Короткие новости Go
Иногда самые полезные вещи — самые короткие. Как команды Unix:
➡️ Послушать подкаст
Кратко про наши курсы: скидки до конца октября!
🐸 Библиотека Go-разработчика
#GoLive
Иногда самые полезные вещи — самые короткие. Как команды Unix:
ls, cd, rm — всё по делу, ничего лишнего. Недавний эпизод подкаста Cup o' Go взял этот принцип на вооружение и выдал порцию Go-новостей без воды. Кратко про наши курсы: скидки до конца октября!
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👾1
💥 Октябрь — месяц апгрейда!
До конца этого месяца действует скидка 40% на все курсы Proglib Academy(кроме AI-агентов, ML для старта и математики) .
Под акцию попал и наш хит — курс «Алгоритмы и структуры данных».
👨💻 Он подойдёт джунам, мидлам и всем, кто хочет писать код осознанно, а не наугад.
👨🏫 Преподаватели — инженеры из Яндекса и ВШЭ.
🎓 Сертификат по итогам обучения — в портфолио.
➖ 47 видеоуроков и 150 практических задач;
➖ поддержка преподавателей и чат;
➖ доступ к материалам на 12 месяцев.
Полная программа курса тут 👈
👉 Остальные курсы
До конца этого месяца действует скидка 40% на все курсы Proglib Academy
Под акцию попал и наш хит — курс «Алгоритмы и структуры данных».
👨💻 Он подойдёт джунам, мидлам и всем, кто хочет писать код осознанно, а не наугад.
👨🏫 Преподаватели — инженеры из Яндекса и ВШЭ.
🎓 Сертификат по итогам обучения — в портфолио.
➖ 47 видеоуроков и 150 практических задач;
➖ поддержка преподавателей и чат;
➖ доступ к материалам на 12 месяцев.
Полная программа курса тут 👈
👉 Остальные курсы
🥱2
Когда программа запускается, операционная система выделяет ей память. Но не всю сразу одной кучей — память организована в разные области, каждая со своим назначением. Две самые важные из них — стек и хип.
Стек: быстрый и дисциплинированный
Представьте стопку тарелок. Положили одну, сверху ещё одну, потом ещё. Снимаете тарелки строго сверху — это и есть принцип работы стека. Последним пришёл — первым ушёл, то есть LIFO.
В стеке хранятся локальные переменные функций и информация о вызовах. Когда вызываете функцию, для неё создаётся стековый фрейм — туда помещаются все её параметры и локальные переменные.
Хип: гибкий и непредсказуемый
Хип — это большая область памяти для динамического выделения. Здесь нет строгого порядка. Вы можете запросить память когда угодно, освободить в любой последовательности, хранить сколько угодно, в пределах доступной памяти.
В хипе размещаются объекты, которые должны жить дольше одной функции, или размер которых заранее неизвестен. В языках с ручным управлением памятью вы сами очищаете память. В языках со сборщиком мусора тот сам решает, когда удалять неиспользуемые объекты.
Практический пример:
func createUser(name string) *User {
count := 42 // в стеке
user := &User{Name: name} // escape to heap
return user
}
func processData() {
data := make([]byte, 100) // скорее всего в стеке
// ... используем data только внутри функции
}Переменная
count останется в стеке и исчезнет при выходе из функции. Структура User уйдёт в хип, потому что мы возвращаем указатель на неё — компилятор видит, что данные сбегают из функции.Слайс
data может остаться в стеке, если компилятор убедится, что он не покидает функцию и его размер разумен.Как Go решает, что куда положить
Go использует escape analysis во время компиляции. Компилятор анализирует код и решает, может ли переменная безопасно жить в стеке:
// Останется в стеке
func stackAlloc() {
x := 42
fmt.Println(x)
}
// Уйдёт в хип
func heapAlloc() *int {
x := 42
return &x // escape: возвращаем указатель
}
Можете проверить сами:
go build -gcflags="-m" your_file.go
Компилятор покажет, какие переменные сбегают в хип и почему.
В Go вы не управляете памятью вручную — компилятор и runtime делают это за вас. Но понимание разницы между стеком и хипом помогает писать эффективный код.
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍15
🎓 Как вайб-кодинг меняет рынок IT-образования
В карточках разобрали, как университеты и онлайн-школы перестраивают программы под новую реальность, где разработчик становится дирижёром, а не исполнителем.
➡️ Узнать как ИИ меняет обучение
🐸 Библиотека Go-разработчика
В карточках разобрали, как университеты и онлайн-школы перестраивают программы под новую реальность, где разработчик становится дирижёром, а не исполнителем.
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱23🌚6❤3🤩2🤔1
🖇 Человекопонятные адреса для локальных серверов
Caddy — это реверс-прокси, который превращает ваши localhost:8081, localhost:9000 в красивые myapp.localhost, blog.localhost.
Предположим, у вас есть локальный сервер на порту 9000. После установки Caddy выполните всего одну команду:
Теперь ваш сервер доступен по адресу
Также можно создать Caddyfile с конфигурацией:
Пусть все ваши проекты будут доступны по человекопонятным адресам вместо путаницы с портами.
➡️ Репозиторий Caddy
🐸 Библиотека Go-разработчика
#GoToProduction
Caddy — это реверс-прокси, который превращает ваши localhost:8081, localhost:9000 в красивые myapp.localhost, blog.localhost.
Предположим, у вас есть локальный сервер на порту 9000. После установки Caddy выполните всего одну команду:
caddy reverse-proxy --from myserver.localhost --to :9000
Теперь ваш сервер доступен по адресу
https://myserver.localhost. Бонус: Caddy автоматически предоставляет локальные TLS-сертификаты Также можно создать Caddyfile с конфигурацией:
myapp.localhost {
reverse_proxy :9000
}
myhugoblog.localhost {
reverse_proxy :1313
}Пусть все ваши проекты будут доступны по человекопонятным адресам вместо путаницы с портами.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍20❤2
Please open Telegram to view this post
VIEW IN TELEGRAM
😁15❤5🥱2
Работа со строками в 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
Главное правило: всегда измеряйте! Не доверяйте интуиции — используйте бенчмарки.
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31❤4🌚1
Инженер с 10+ годами опыта провалил интервью, потому что не смог за 45 минут решить задачу на динамическое программирование, которую не видел с универа.
Есть аргументы за решение задач не собеседовании и против.
Никто не будет решать задачки с литкода на работе, но и код с O(n²) вместо O(n log n) сто процентов положит прод под нагрузкой.
Админ один раз перенервничал и забыл как найти середину отрезка на плоскости. Это полностью заруинило ему алгоритмическую секцию.
💬 Как вы думаете — задачи на собесе это ту мач или имеют место быть? Ждём ваше мнение в комментариях 👇
#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
❤5
С вами библиотека Go-разработчика и мы освежаем в памяти прошедшую неделю.
— Черновик про релиз Go 1.26
Контекстные сетевые функции, классификация переменных в go/types, кастомизация сканирования БД и полная поддержка Windows file flags
— Подборка курсов для повышения скиллов
— 14 вопросов, после которых вам не перезвонят
— Свежий Cup o' Go
#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Please open Telegram to view this post
VIEW IN TELEGRAM
😁53
Forwarded from Библиотека Go для собеса | вопросы с собеседований
Это структура, определённая как
Зачем она нужна
• Неэкспортируемую пустую структуру часто используют, чтобы обозначить, что тип
• Так как struct{} занимает
set := map[string]struct{}{}
set["apple"] = struct{}{}• Пустая структура идеальна для
done := make(chan struct{})
go func() {
// работа
done <- struct{}{}
}()
<-done• Если структура неэкспортируема, она не видна за пределами пакета — удобно для
Please open Telegram to view this post
VIEW IN TELEGRAM
👍11❤4🥱3
🧠 Готовишься к собесам, а ноутбук еле тянет IDE?
Самое время прокачать скиллы и апгрейднуть железо!
Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!
📚 Среди курсов:
▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.
▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.
▫️ Python, математика для DS, основы IT и другие направления.
👉 Принять участие
Самое время прокачать скиллы и апгрейднуть железо!
Proglib Academy разыгрывает MacBook Pro 14 (M3 Pro, 36 GB, 1 TB SSD) 💻
Купи любой наш курс до 15 ноября → пройди 2 недели обучения → напиши куратору #розыгрыш. Всё, ты в игре!
📚 Среди курсов:
▫️ Алгоритмы и структуры данных — топ для подготовки к собесам в Яндекс и FAANG.
▫️ Архитектуры и шаблоны проектирования — чтобы думать как senior.
▫️ Python, математика для DS, основы IT и другие направления.
👉 Принять участие
🥱9❤1
Между «накинуть 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
Всё. Балансировщик поднимается на указанном порту и начинает работу.
#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11
🧑💻 Подготовка к 6-дневке: инструкция для взрослых
Шаг 1: Осознать, что выбора нет
Шаг 2: Смириться
Шаг 3: ???
Шаг 4: PROFIT
💬 А вы готовы? Как проходит второй понедельник? Или у вас будет две пятницы?
🐸 Библиотека Go-разработчика
#GoTalk
Шаг 1: Осознать, что выбора нет
Шаг 2: Смириться
Шаг 3: ???
Шаг 4: PROFIT
#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
😁8❤2
Одна из классических ошибок начинающих Go-разработчиков — определять интерфейсы слишком рано и слишком широко. Интерфейс должен описывать поведение, которое вам нужно, а не всё, что умеет делать структура.
Плохо:
type Database interface {
Create()
Read()
Update()
Delete()
}Здесь мы создали толстый интерфейс со всеми возможными операциями. Но что если вашему коду нужно только читать данные?
Хорошо:
type Reader interface {
Read() ([]byte, error)
}Узкий интерфейс, описывающий ровно то, что нужно конкретному потребителю.
Думайте как потребитель: «Что мне нужно от этой зависимости?» — и определяйте интерфейс исходя из ответа. Это чистый YAGNI для интерфейсов — не определяй методы, пока они не нужны.
#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍19🌚2❤1