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

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

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

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

РКН: https://gosuslugi.ru/snet/67a4a8c2468
Download Telegram
🔒 Оптимистическая vs пессимистическая блокировка

Представьте: интернет-магазин продает последний товар сразу трем покупателям, потому что база не успела обновиться.

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

Решение — блокировки в базе данных.

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

➡️ Подробнее про блокировки

🐸Библиотека Go-разработчика
Please open Telegram to view this post
VIEW IN TELEGRAM
5👍2🔥2
⚙️ Как из микросервисов сделать монолит

Мы привыкли слышать: «Надо уходить в микросервисы». Но что если это не панацея или стало только хуже? Разберёмся как вернуться к монолиту.

Как это сделать на практике

1. Разобраться в текущей архитектуре

Карта сервисов, API, базы, зависимости. Определяем, что реально стоит объединять.

2. Слить код в один проект

Из множества репозиториев → единый монолит.
Каждый сервис становится модулем внутри одного приложения.

3. Убрать сетевые вызовы

HTTP/gRPC заменяем на обычные вызовы методов.
Больше никаких прокси, discovery и mesh.

4. Централизовать работу с данными

Объединяем схемы в одну БД или хотя бы в одно хранилище.
Транзакции снова становятся простыми и атомарными.

5. Упростить инфраструктуру

Один артефакт, один деплой, один пайплайн.
API Gateway и прочие прослойки уходят в прошлое.

Монолитизация — не шаг назад, а инструмент. Иногда именно он позволяет бизнесу двигаться быстрее.

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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
😁26👍102🔥1👾1
📎 Понятно, что ничего не понятно

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

Сегодня делимся с вами промптом для анализа логов:
Проанализируй предоставленный файл с логами приложения на предмет выявления неординарного поведения или потенциальных индикаторов багов. Обрати внимание на аномальные временные метки, повторяющиеся ошибки, неожиданные статусы и отклонения от стандартных паттернов работы. В конце дай подробный отчет с описанием найденных подозрительных событий и рекомендациями для дальнейшего расследования.


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

#буст
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🧑‍💻 Программист не кодит

Когда вы шли в разработку, наверняка думали: «буду писать код целыми днями». Но реальность другая — у многих бекендеров до 90 % времени уходит не на код.

Реальность такова: большая часть дня уходит не на написание новых фич, а на поддержание, координацию, деплой, отладку, ответ на письма и тикеты.

Получается, мы больше оркестрируем процессы, чем пишем фичи. И это не обязательно плохо: именно эти «не-кодовые» задачи держат систему живой и рабочей.

Но есть обратная сторона: многие начинают чувствовать себя не разработчиками, а менеджерами тасков.

💬 А у вас как? Чувствуете, что реально кодите меньше, чем ожидали, или находите баланс между кодом и всей этой скучной работой?

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
7👍1
This media is not supported in your browser
VIEW IN TELEGRAM
📅 24 сентября в 19:00 МСК — бесплатный вебинар с Максимом Шаланкиным.

Тема: «ИИ-агенты: новая фаза развития искусственного интеллекта».

🔹 Почему все говорят про ИИ-агентов и куда вливаются миллиарды инвестиций.
🔹 Чем они отличаются от ChatGPT и обычных ботов.
🔹 Как работает цикл агента: восприятие → планирование → действие → обучение.
🔹 Живое демо простого агента.
🔹 Потенциал для бизнеса: автоматизация процессов и ROI до 80%.

Не придёшь — будешь потом рассказывать, что «агенты — это как чат-боты», и ловить косые взгляды от коллег 😏

👉 Регистрируйтесь через форму на лендинге
😁1
🔄 Как работает Round Robin

Round Robin — простой и популярный способ распределения ресурсов. Его суть: все задачи выполняются по очереди и получают одинаковый квант времени.

Как это работает:

1. Задача получает фиксированное время (например, 50 мс).
2. Если она успевает завершиться — удаляется из очереди.
3. Если нет — ставится в конец, и очередь продолжается.

По сути, это как дейлик: каждый участник получает ровно минуту, потом слово передаётся следующему.

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

#GoVisual
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
💡 Структуры в Go: больше, чем просто поля

На первый взгляд, структура в Go — это просто набор полей. Но стоит копнуть глубже, и начинают всплывать вопросы:

— почему структура весит больше, чем сумма её полей?
— почему один struct можно сравнивать и использовать как ключ в map, а другой — нет?

Ниже заглянем под капот и разберёмся с этим.

➡️ Память, выравнивание и паддинг

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

type A struct {
B bool // 1 byte (+7 padding)
I int64 // 8 bytes
} // Sizeof(A) = 16

type B struct {
I int64 // 8 bytes
B bool // 1 byte (+7 padding for struct alignment)
} // Sizeof(B) = 16 (в данном примере одинаково, но порядок важен при большем числе полей)


В итоге структура весит не 9, а 16 байт. Если перепутать порядок полей в большой структуре — потратите кучу памяти впустую. Иногда простая перестановка int64 выше bool экономит пространство на диске.

➡️ Сравнимость и ключи мапы

В Go структуры можно сравнивать оператором == и использовать как ключи в map. Но есть важное условие: все поля должны быть сравнимыми.

type KeyGood struct {
ID int
Name string
} // можно сравнивать и использовать как ключ

type KeyBad struct {
Data []byte
} // compile error: []byte несравнимый


Обходные пути:

• Фиксированный массив вместо среза:
type KeyArr struct {
Digest [16]byte
}


• Строка как ключ (создаёт копию, но работает):
key := string(digestBytes)
m := map[string]string{key: "value"}


• Собственный тип с хэшированием — можно хранить хэш массива байт в uint64 или в строке, и использовать как ключ.

Зная нюансы, вы пишете не просто рабочий код, а код, который работает эффективно и предсказуемо.

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
171👍1
⚡️ Бесплатный вебинар — ИИ-агенты: новая фаза развития AI

24 сентября в 19:00 МСК состоится бесплатный вебинар с Максимом Шаланкиным — Data Science Team Lead в финтех-команде MWS, а познакомиться с ним ближе можно в его тг-канале.

Тема:
«ИИ-агенты: новая фаза развития искусственного интеллекта».


На вебинаре разберёмся, почему агенты — это следующий шаг после ChatGPT, чем они отличаются от обычных моделей и как уже приносят бизнесу ROI до 80%. А дальше я покажу, как эта тема ложится в наш курс по ИИ-агентам, который разработан под руководством Никиты Зелинского.

Подробности рассказываем в гс выше — включай, чтобы не пропустить.
🥤 Как писать универсальный код в Go

Дженерики в Go позволяют писать один алгоритм для разных типов без копипасты и без interface{}. Это про выразительность и про безопасность типов — меньше дублирования, больше проверок на этапе компиляции.

Пример сравнения разных типов одним методом:
func Compare[T ~int | ~int64 | ~float64 | ~string](a, b T) int {
if a < b {
return -1
} else if a > b {
return 1
}
return 0
}


Типобезопасная коллекция без приведения типов:
type Set[T comparable] map[T]struct{}

func NewSet[T comparable]() Set[T] { return make(Set[T]) }

func (s Set[T]) Add(v T) { s[v] = struct{}{} }
func (s Set[T]) Has(v T) bool { _, ok := s[v]; return ok }
func (s Set[T]) Delete(v T) { delete(s, v) }

func main() {
users := NewSet[string]()
users.Add("alice")
users.Add("bob")

nums := NewSet[int]()
nums.Add(1)
nums.Add(2)

fmt.Println(users.Has("bob")) // true
fmt.Println(nums.Has(3)) // false
}


Практические советы

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

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
6🥱4👍2
🆕 Дайджест недели

Сегодня последний день недели и это значит, что пришло время для сборника материалов.

Время высказаться

Команда Go открыла ежегодный опрос разработчиков — Go Developer Survey 2025. Пройти его можно до 30 сентября.

Outbox-паттерн в Go + Postgres

Вместо того чтобы сразу пушить событие в брокер, сервис пишет его в таблицу outbox в той же транзакции, что и бизнес-изменение. Дальше отдельный воркер периодически читает «необработанные» записи, публикует их и помечает как processed. Так достигается at-least-once доставка, а потребители обязаны быть идемпотентными.

Новый Cup o' Go

В свежем выпуске подкаста Cup o’ Go — обзор новостей: экспериментальный JSON API для Go, опрос разработчиков 2025 года, статья о том, почему стоит тестировать состояние, а не взаимодействия, и даже история о том, как линтер «сломал» код.

Go Task v3.45.3

Оптимистическая vs пессимистическая блокировка

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

#GoLive
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
➡️ Выбираем направление на неделю

Контент недели — в ваших руках.
Мы соберем материалы, практики и гайды именно по выбранному направлению.

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

#GoTalk
Please open Telegram to view this post
VIEW IN TELEGRAM
🕵️ Обнаружение утечек горутин

Утечки горутин не всегда заметны — сервис вроде работает, но число горутин медленно растёт.

Проверить можно прямо в тесте:
func TestHandler_TestLeaks(t *testing.T) {
initial := runtime.NumGoroutine()
err := testHandler()
require.NoError(t, err)
time.Sleep(100 * time.Millisecond) // время на очистку
final := runtime.NumGoroutine()
assert.InDelta(t, initial, final, 2, "Есть утечка")
}


Также используйте pprof/trace для проверки количества горутин в /debug/pprof/goroutine и трассировки их жизненного цикла

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

#GoToProduction
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14
🎧 Топ вакансии недели

Go-разработчик
с удалёнкой в Москве и ЗП до 400 тысяч ₽.

Гибрид для Go-разработчика с вилкой 250-400 тысяч ₽.

Мидл эникей на Go с гибридом в Москве.

Вакансия для тех, кто хочет стать частью команды ProgLib — Бустер

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

#GoWork
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Не пропустите событие осени для AI-комьюнити

24 сентября, 19:00 Мск — бесплатный вебинар с Максимом Шаланкиным «ИИ-агенты: новая фаза развития искусственного интеллекта»

😤 Пока все спорят, «боты это или нет», мы покажем, как работают настоящие агенты: с планированием, инструментами и памятью. За час Максим разберёт:
— почему ИИ-агенты сейчас на пике инвестиций
— чем они отличаются от ChatGPT и обычных моделей
— цикл агента: восприятие → планирование → действие → обучение
— живое демо простого агента
— как бизнес уже получает ROI до 80%

⚡️ Хотите спросить у Максима всё, что обычно остаётся «за кадром»? Ловите шанс — только в прямом эфире.

Мест мало, регистрация закроется, как только забьём комнату
😁21🤔1
🛠 Как работает JWT

JWT (JSON Web Token) — это компактный способ передачи информации между участниками через JSON-объект, защищённый подписью.

Что происходит по шагам:

• Аутентификация — пользователь вводит логин/пароль, сервер проверяет их и создаёт токен.

• Формирование токена из заголовка, пейлода и подписи. Всё это кодируется в Base64.

• Использование — клиент хранит токен (обычно в localStorage или cookie) и отправляет его в заголовке Authorization: Bearer <token> при каждом запросе.

• Проверка — сервер расшифровывает токен, сверяет подпись и срок действия. Если всё совпадает, запрос считается доверенным.

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

#GoVisual
Please open Telegram to view this post
VIEW IN TELEGRAM
👍14🥱3
🏭 Фабрика: когда конструктор — это функция

В классическом ООП фабрика — это отдельный объект, который возвращает разные реализации интерфейса.
В Go всё проще: фабрика = обычная функция, которая возвращает интерфейс или конкретный тип.

Представьте, у нас есть сервис оплаты. Способов много: карта, СБП, крипта. Хотим переключаться динамически, но при этом не тянуть жёсткие зависимости в код.

Пример:
package main

import "fmt"

// общий контракт
type Payment interface {
Pay(amount float64) string
}

// конкретные реализации
type Card struct{}
func (c Card) Pay(amount float64) string {
return fmt.Sprintf("💳 Оплата картой: %.2f₽", amount)
}

type SBP struct{}
func (s SBP) Pay(amount float64) string {
return fmt.Sprintf("📲 Перевод через СБП: %.2f₽", amount)
}

type Crypto struct{}
func (c Crypto) Pay(amount float64) string {
return fmt.Sprintf("₿ Криптой: %.2f₽", amount)
}


И сама фабрика:
// фабрика по выбору метода
func PaymentFactory(method string) Payment {
switch method {
case "card":
return Card{}
case "sbp":
return SBP{}
case "crypto":
return Crypto{}
default:
return nil
}
}


Использование:
func main() {
pay := PaymentFactory("sbp")
fmt.Println(pay.Pay(1599.50))
}


В стандартной библиотеке это повсеместно: http.NewRequest(), json.NewEncoder().

Такой подход отлично дружит с тестированием и моками. Хотите заменить оплату через карту на СБП или крипту? Просто подставьте другой конструктор.

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

#GoDeep
Please open Telegram to view this post
VIEW IN TELEGRAM
👍35🔥1👾1
✏️ Задача дня: 3Sum

Дан массив целых чисел nums. Требуется найти все уникальные тройки (a, b, c), такие что a + b + c = 0. Порядок элементов в тройке не важен, дубликаты недопустимы.

Идея оптимального решения

1. Сортируем массив (O(n log n)), чтобы упростить поиск и контроль дубликатов.

2. Фиксируем первый элемент i, затем две указки l и r («два указателя») пробегают подмассив справа/слева:

Если сумма < 0 → сдвигаем l++,

Если сумма > 0 → сдвигаем r--,

Если сумма == 0 → сохраняем тройку и пропускаем дубликаты вокруг l и r.

3. Пропускаем дубликаты и для i, чтобы не повторять стартовую точку.

Сложность: O(n^2) по времени и O(1) доп. памяти не считая результата.

Реализация:
package main

import (
"fmt"
"sort"
)

func threeSum(nums []int) [][]int {
sort.Ints(nums)
n := len(nums)
res := make([][]int, 0)

for i := 0; i < n; i++ {
// Пропускаем одинаковые стартовые значения
if i > 0 && nums[i] == nums[i-1] {
continue
}
// Ранний выход: дальше только положительные
if nums[i] > 0 {
break
}

l, r := i+1, n-1
for l < r {
sum := nums[i] + nums[l] + nums[r]
switch {
case sum < 0:
l++
case sum > 0:
r--
default:
res = append(res, []int{nums[i], nums[l], nums[r]})
// Пропускаем дубликаты для l
lVal := nums[l]
for l < r && nums[l] == lVal {
l++
}
// Пропускаем дубликаты для r
rVal := nums[r]
for l < r && nums[r] == rVal {
r--
}
}
}
}
return res
}

func main() {
examples := [][]int{
{-1, 0, 1, 2, -1, -4},
{0, 0, 0, 0},
{-2, 0, 1, 1, 2},
}

for _, nums := range examples {
fmt.Println("Input:", nums)
fmt.Println("Triplets:", threeSum(append([]int{}, nums...)))
}
}


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

#ReadySetGo
Please open Telegram to view this post
VIEW IN TELEGRAM
👍136