Библиотека Go-разработчика | Golang – Telegram
Библиотека Go-разработчика | Golang
23.7K subscribers
2.39K photos
48 videos
87 files
4.82K links
Все самое полезное для Go-разработчика в одном канале.

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

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

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

РКН: https://gosuslugi.ru/snet/67a4a8c2468
Download Telegram
⚙️ Docker команды, которые должен знать разработчик

Сколько раз вы открывали терминал и забывали простую Docker команду? Гугл в помощь, потом опять ищете то же самое через неделю. Рассказываем про команды, которые нужны в реальной работе.

Вам нужно видеть, какие контейнеры работают прямо сейчас:
docker ps


Это покажет только живые контейнеры. Но если контейнер упал или его остановили, он исчезнет из списка.

Чтобы увидеть всё, включая мёртвые:
docker ps -a


Самая частая команда в разработке:
docker run -d -p 8080:80 nginx


Разбираем:
-d — запустить в фоне, чтобы терминал не занимался.
-p 8080:80 — проксировать локальный порт 8080 на порт 80 внутри контейнера.
nginx — образ, который запускаем.

Результат: контейнер крутится в фоне, вы можете открыть http://localhost:8080 и увидите nginx.

Контейнер поднялся, поэкспериментировали, теперь нужно его убить:
docker stop имя-или-id


Контейнер остановится, но останется на диске.

Если нужно удалить совсем:
docker rm имя-или-id


Или в один ход — остановить и удалить:
docker rm -f имя-или-id


Флаг -f форсирует удаление даже если контейнер работает.

Посмотреть все образы у вас на машине:
docker images


Удалить образ, если он вам больше не нужен:
docker rmi название-образа


Если удалите образ, контейнеры которые на нём основаны, перестанут работать.

Контейнер падает или работает странно? Посмотрите логи:
docker logs имя-или-id


Это покажет всё что контейнер вывел в stdout.

Можно добавить флаг -f чтобы следить в реальном времени:
docker logs -f имя-или-id


Иногда нужно залезть внутрь контейнера и что-то проверить. Откройте интерактивный шелл:
docker exec -it имя-или-id bash


Флаг -it означает интерактивный терминал. Теперь вы внутри, можете запускать команды, смотреть файлы, отлаживать.

Ещё полезно посмотреть детали контейнера:
docker inspect имя-или-id


Будет JSON со всей информацией: какие переменные окружения, какие портами, версии образа, сетевая конфигурация.

Со временем контейнеры и образы накапливаются. Чистим:
docker system prune -a


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

Контейнер падает, данные теряются — такое быть не должно. Для этого есть тома:
docker volume create my_volume


Теперь у вас есть том. Запускаете контейнер и монтируете том внутрь:
docker run -d -v my_volume:/data nginx


Флаг -v монтирует том my_volume в папку /data внутри контейнера. Когда контейнер упадёт, данные в томе остаются. Запустите контейнер снова — данные на месте.

По умолчанию контейнеры могут общаться через IP адреса, но это хрупко. Правильнее создать свою сеть:
docker network create my_network


Теперь запускаете контейнеры в этой сети:
docker run -d --network my_network --name api nginx
docker run -d --network my_network --name db postgres


Контейнеры внутри сети видят друг друга по имени. Это удобнее чем помнить IP адреса.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍29🔥3🥱1
🛠 Как найти и починить утечки, которые валят API

API падает каждый день? Память растёт, горутины множатся, потом крах. Это не магия — это утечки ресурсов. Вот как их найти и убить.

Шаг 1: Собрать доказательства перед тем как гадать

Не начинайте с предположений. Сначала соберите логи. Ищите паттерны: растут ли таймауты, появляются ошибки «context canceled», скачет ли error rate?

Heap и goroutine профили. Это главное. Добавьте pprof endpoint, если его нет:
import _ "net/http/pprof"

go func() {
log.Println(http.ListenAndServe(":6060", nil))
}()


На следующем инциденте вытащите профили:
curl localhost:6060/debug/pprof/heap > heap.pb
curl localhost:6060/debug/pprof/goroutine?debug=2 > goroutines.txt


Проверьте лимиты: /proc/<pid>/limits, количество открытых файловых дескрипторов, состояние сокетов.

Шаг 2: Прочитать профили и понять, что протекает

Откройте goroutine профиль текстом — там все ответы:
go tool pprof -http=:8080 heap.pb


Что нужно найти:

• Горутины в CLOSE_WAIT. Это сокеты, которые никто не закрыл нормально.

• Горутины, зависшие на channel send/receive. Если тысячи горутин ждут отправить или получить из канала — канал где-то забился или заблокирован.

• Горутины в syscall. Много горутин ждут на сетевых операциях — это может быть утечка соединений или зависание на стороне сервера.

Шаг 3: Найти корни утечек в коде

Три главных виновника:

• Горутины без контекста. Запустили горутину для async операции, но не гарантировали её завершение:
// Плохо: горутина может зависнуть
go func() {
resp, _ := http.Get(url)
// ...
}()

// Хорошо: контекст отменяет работу
go func(ctx context.Context) {
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, _ := httpClient.Do(req)
}(r.Context())


• HTTP клиенты без переиспользования. Создаёте нового клиента на каждый запрос:
// Плохо: новый Transport на каждый вызов
func handleRequest(w http.ResponseWriter, r *http.Request) {
client := &http.Client{}
resp, _ := client.Get("https://api.example.com/data")
}

// Хорошо: переиспользуем один клиент
var httpClient = &http.Client{
Transport: &http.Transport{
MaxIdleConns: 200,
MaxIdleConnsPerHost: 100,
IdleConnTimeout: 90 * time.Second,
},
}


• Неограниченные очереди. На пике нагрузки канал растёт без предела:
// Плохо: неограниченный канал
jobs := make(chan Job)

// Хорошо: ограничиваем размер
jobs := make(chan Job, 1000)

select {
case jobs <- job:
// принято
default:
http.Error(w, "перегружены", http.StatusServiceUnavailable)
}


Чтобы не падать в проде можно попробовать имитировать нагрузку на дев стенде:
# Генерируем нагрузку
ab -n 100000 -c 100 http://localhost:8080/endpoint

# В другом терминале снимаем профиль каждую минуту
for i in {1..60}; do
curl localhost:6060/debug/pprof/goroutine?debug=1 > goroutine_$i.txt
sleep 60
done


Растёт ли количество горутин? Если да — утечка. Если нет — ложная тревога.

Не полагайтесь только на профили. Мониторьте в реальном времени:
// Метрика: количество горутин
runtime.NumGoroutine()

// Метрика: память
var m runtime.MemStats
runtime.ReadMemStats(&m)
m.Alloc // текущее использование

// Метрика: открытые файловые дескрипторы (Linux)
files, _ := ioutil.ReadDir("/proc/self/fd")
len(files) // количество открытых fd


Выставляйте эти метрики в Prometheus или что у вас есть. Алерты на рост горутин выше нормы — это первый звоночек.

Не решайте задачу вслепую. Профилируйте, смотрите данные, ищите паттерны. Утечки это не магия — это просто ресурсы, которые вы забыли закрыть.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍26🔥74😢1
✏️ FizzBuzz — классика собеседований

Задача проста на вид, но открывает много вопросов на интервью. Вот почему её так любят спрашивать.

Дано число n. Нужно вернуть массив строк, где для каждого числа от 1 до n:

• если кратно и 3 и 5 — «FizzBuzz»
• если кратно 3 — «Fizz»
• если кратно 5 — «Buzz»
• иначе — само число как строку

Решение:
func fizzBuzz(n int) []string {
res := make([]string, n)
for i := 1; i <= n; i++ {
res[i-1] = strconv.Itoa(i)
if i % 3 == 0 { res[i-1] = "Fizz" }
if i % 5 == 0 { res[i-1] = "Buzz" }
if i % 15 == 0 { res[i-1] = "FizzBuzz" }
}
return res
}


Число 15 — это наименьшее общее кратное чисел 3 и 5. Когда число одновременно делится на 3 и на 5, оно всегда делится на 15.

На собеседовании сначала напишите просто, потом обсудите улучшения. FizzBuzz — не про трюки синтаксиса, а про чистоту мышления и умение общаться с интервьюером.

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

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱9👍6😁3🤔1
🧑‍💻 Среда или понедельник

Как у вас началась рабочая трёхдневка? У админа сбились абсолютно все настройки по пониманию какой сейчас день недели. Тяжелее только новогодние праздники.

💬 Работаете или взяли хитрый отпуск? Ждём вас в комментах 👇

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
😁9🥱1
⚙️ GoCrypt 1.1.0: теперь быстрее

GoCrypt изначально просто проходил через все поля структуры на каждый вызов, искал теги, выполнял рефлексию. Для больших структур это замедлялось быстро.

Новая версия 1.1.0 это переработала.

Раньше каждый вызов Encrypt() и Decrypt() переанализировал структуру с нуля. Если вы обрабатываете пользователя с 15 полями, где только 3–4 нужно шифровать, библиотека изучала все 15. В тысячный раз.

Теперь типы кешируются через sync.Map. Первый проход — сохраняются информация о том, какие поля нужны. Все последующие операции просто смотрят в кеш.

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

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍201😁1
🔒 Когда fmt.Sprintf становится бомбой

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

Пара строк кода, которые кажутся логичными и работают в тестах. Но в боевых условиях это становится открытой дверью в вашу базу данных.

Когда вы склеиваете SQL-запрос из частей, вы решаете за базу данных, что считать кодом, а что — данными. И вы почти гарантированно ошибаетесь.

Хакер, в отличие от вас, знает это. Он понимает, что можно передать в поле username и заставить его работать как код. Он не пытается угадать пароль — он меняет саму структуру запроса.

Параметризованные запросы — это не украшение, а архитектура

Разница между уязвимым и безопасным кодом — это не регулярные выражения или специальные функции для очистки. Это просто разделение: запрос идёт одним пакетом, данные — другим.

// Сначала структура...
query := "SELECT id, username, email FROM users WHERE username = ?"
// ...потом данные
err := db.QueryRow(query, username).Scan(&id, &uname, &email)


Драйвер БД уже знает, что делать. Он не будет интерпретировать данные как команды.

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

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍212
🤨 Игнорирование контекста — это путь боли

Новичок пишет код примерно так:
res, err := http.Get(url)


Выглядит невинно, но если вызов зависнет, то зависнет и горутина. Навсегда. Нет таймаута, нет способа его отменить. Сервис просто накапливает горутины, пока не упадёт.

Профессионалы всегда передают контекст через все слои приложения:
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
res, err := http.DefaultClient.Do(req)


Они распространяют его на весь путь — от HTTP хендлера через бизнес-логику до репозиториев:
func (r *UserRepo) Get(ctx context.Context, id int) (*User, error) {
// ctx здесь и управляет отменой, и ловит таймауты
}


Это не просто хорошая практика — это основа надёжности.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍28🤔51💯1
⚙️ Go-библиотека для интеграции OAuth

gologin предоставляет цепочки http.Handler-ов для аутентификации через Google, GitHub, Twitter, Bitbucket, Tumblr или любых других OAuth1 и OAuth2 провайдеров.

Вместо того, чтобы вручную парсить OAuth-потоки, обрабатывать CSRF-токены и делать API-запросы за данными пользователя, вы просто подключаете готовые обработчики и получаете аутентифицированного пользователя в контексте запроса.

Быстрый старт

Интегрировать вход через GitHub занимает всего несколько строк:
import (
"github.com/dghubble/gologin/v2"
"github.com/dghubble/gologin/v2/github"
"golang.org/x/oauth2"
githubOAuth2 "golang.org/x/oauth2/github"
)

config := &oauth2.Config{
ClientID: "YourGithubClientID",
ClientSecret: "YourGithubClientSecret",
RedirectURL: "http://localhost:8080/callback",
Endpoint: githubOAuth2.Endpoint,
}

mux := http.NewServeMux()
mux.Handle("/login",
github.StateHandler(gologin.DefaultCookieConfig,
github.LoginHandler(config, nil)))
mux.Handle("/callback",
github.StateHandler(gologin.DefaultCookieConfig,
github.CallbackHandler(config, issueSession(), nil)))


Готово. Пользователь нажимает на /login, перенаправляется на GitHub, а затем на /callback с кодом авторизации.

Для веб-приложений используются LoginHandler и CallbackHandler, которые управляют редиректами.

Для мобильных приложений есть TokenHandler, который работает с токенами, передаваемыми напрямую. Twitter, например, включает специальный TokenHandler именно для таких случаев.

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

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1651
🎁 И мозг прокачать, и макбук утащить!

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

Условия:

1️⃣ Покупаешь любой курс Proglib до 15 ноября.
2️⃣ Проходишь минимум 2 учебные недели (можно осилить за два вечера).
3️⃣ Пишешь куратору в чат своего курса: #розыгрыш.

Что за курсы?

Математика для Data Science (6 месяцев боли и просветления).
Основы Python, ML, алгоритмы, AI-агенты и даже курс для тех, кто в IT, но не кодит.

👉 Участвовать в розыгрыше
🥱32🤔1🤩1
💻 От логирования к передаче вверх

Go известен своей простотой, но именно в этой простоте скрыта мощная возможность — передача ошибок вверх по стеку вызовов. Часто начинающие разработчики просто логируют ошибку и возвращают nil, теряя всю информацию о контексте:
user, err := repo.GetUser(id)
if err != nil {
log.Println("failed to get user:", err)
return nil
}


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

Вот как это делают опытные разработчики:
user, err := repo.GetUser(ctx, id)
if err != nil {
return nil, fmt.Errorf("get user %d: %w", id, err)
}


%w — это ключ к вложенным ошибкам в Go 1.13 и новее. Такой подход сохраняет смысл ошибки и ее цепочку, что помогает в отладке и трассировке.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍25🥱63
🤩 Finally — отсортированные часы

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

#GoGiggle
Please open Telegram to view this post
VIEW IN TELEGRAM
😁31👾3
📰 Дайджест недели

Вот и прошла трёхдневная рабочая неделя. Вспоминаем что произошло.

Ещё один ИИ из Китая

Свежий Cup o' Go

У Firefox новый маскот

Как найти и починить утечки, которые валят API

GoCrypt 1.1.0

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
💻 ВАЖНО: макбук ещё не забрали!

Proglib.academy продолжает розыгрыш MacBook Pro 14» (M3 Pro, 36 Гб, 1 Тб SSD).

Что нужно для участия?

— Берёшь любой курс Академии до 15 ноября.
— Проходишь хотя бы 2 недели обучения (можно за два дня).
— Пишешь куратору #розыгрыш. Всё — ты в игре!

Что за курсы?

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

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

▫️ Python, математика для DS, основы IT и другие темы — можно стартовать с нуля или усилить то, что уже знаешь.

👉 Влетай, не думай!
🥱9😁2👍1👾1
⚙️ Структура кода в Go: от папок к доменам

Многие начинающие Go-разработчики организуют проекты, разделяя файлы по типам — например, отдельные папки для моделей, обработчиков, утилит. Такая схема выглядит аккуратно:
/models
/utils
/handlers


Однако за этим скрываются проблемы: тесная связанность кода и круговые зависимости между пакетами.

Современный подход — разделять код по доменам и ответственности. Например, структура может выглядеть так:
/internal
/user
handler.go
service.go
repository.go
/pkg
/config
/logger
/cmd
/api
main.go


Это стандарт для крупных систем, таких как Uber или Cloudflare. Даже команда Go рекомендует именно такой подход.

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
30👍8🌚52😢2
💻 Хочешь MacBook Pro? Просто начни учиться!

Да-да, вы не ослышались: Proglib.academy дарит макбук за учёбу!

Всё просто:

— купи любой курс Академии до 15 ноября;
— пройди 2 недели обучения (можно за два дня);
— напиши куратору в чате курса хэштег #розыгрыш.

📚 Выбирай свой курс:

▫️ «Математика для DS» — для тех, кто хочет уверенно работать с данными;
▫️ «Основы Python» — чтобы начать писать код с нуля;
▫️ «Алгоритмы и структуры данных» — для будущих инженеров;
▫️ «AI-агенты» или «Машинное обучение» — для тех, кто хочет прокачаться в ИИ.

👉 Участвовать в розыгрыше
👍1😁1
💰 Топ-вакансий для Go-разработчиков за неделю

Go Developer — от 3 000 до 7 000 $

Middle GO разработчик на удалёнку

Джун Go разработчик — от 1 700 $

Golang-разработчик — от 200 000 ₽

➡️ Еще больше топовых вакансий — в нашем канале Go jobs

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

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2
🪙 Выложить монетки в лестницу

Дано n монет. Нужно выложить лестницу, где на i-й ступени ровно i монет. Вернуть количество полных рядов лестницы, которые удастся построить.

Наивный перебор даёт O(n), но попробуем быстрее:
func arrangeCoins(n int) int {
left, right := 0, n
for left <= right {
mid := left + (right-left)/2
sum := mid * (mid + 1) / 2
if sum == n {
return mid
}
if sum < n {
left = mid + 1
} else {
right = mid - 1
}
}
return right
}


Вместо перебора каждого уровня, бинарный поиск за O(log n) найдёт точный ответ.

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

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍121
🛒 Black Friday от Proglib.academy!

Только до 30 ноября — скидка 40% на ВСЕ курсы.

Пора добавить в корзину не носки, а новые скиллы: Python, математика для Data Science, AI, алгоритмы и структуры данных, ML.

🎓 Выбирай курс, который реально двинет тебя в карьере, и учись со скидкой.

👉 Учиться со скидкой
👍1