Библиотека Go для собеса | вопросы с собеседований
7.39K subscribers
255 photos
10 videos
1 file
747 links
Вопросы с собеседований по Go и ответы на них.

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

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

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
Когда пригодится default в select

default в Go превращает select в неблокирующую операцию. Если ни один канал не готов, выполнение сразу идёт дальше, без ожидания.

Где это полезно:

Таймауты и поллинг — мгновенно возвращаем управление, если данные ещё не пришли, вместо того чтобы зависнуть в ожидании.

Event loopdefault берёт на себя фоновые задачи и проверки состояния, пока основной поток не простаивает в блокировке.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
Как работает механизм избирательного пробуждения горутин в sync.Cond на уровне структуры notifyList

notifyList содержит два счётчика: wait (сколько горутин встало в очередь) и notify (сколько горутин уже получили сигнал). Когда горутина вызывает Wait(), она атомарно получает текущий тикет из wait, инкрементирует wait и засыпает. Тикет — это её уникальный порядковый номер в очереди.

При вызове Signal() (который внутри вызывает notifyListNotifyOne) атомарно инкрементируется notify. Затем метод проходит по связанному списку горутин и ищет ту, чей тикет равен новому значению notify - 1. Именно она и пробуждается через goready.

Такой подход гарантирует строгий FIFO-порядок пробуждения: горутины получают управление в том же порядке, в котором вставали в очередь. Это исключает голодание и делает поведение sync.Cond предсказуемым при конкурентном доступе.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Может ли стек горутины быть ограниченным по памяти или он растёт сколько угодно

По умолчанию максимальный размер стека горутины — 1 ГБ на 64-битных системах. Это задаётся рантаймом Go и контролируется переменной runtime/debug.SetMaxStack или просто константой в рантайме.

import "runtime/debug"

debug.SetMaxStack(512 * 1024 * 1024) // установить лимит 512 МБ


Если горутина превысит этот лимит, то будет паника.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥7
Что такое сериализация и как она работает в Go

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

Чаще всего это нужно в веб-приложениях и распределённых системах, где данные постоянно путешествуют между сервисами.

Берём структуру и превращаем её в JSON:
type User struct {
Name string
Age int
}

user := User{Name: "Alice", Age: 30}
jsonBytes, _ := json.Marshal(user)
// {"Name":"Alice","Age":30}


Обратно из JSON в структуру:
var user User
json.Unmarshal(jsonBytes, &user)


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍9
Какие есть способы удаления элемента из среза

Удаление с сохранением порядка (O(n))

Используем append для объединения частей слайса:
slice := []int{1, 2, 3, 4, 5}
newSlice := append(slice[:2], slice[3:]...) // [1, 2, 4, 5]


Быстрое удаление без сохранения порядка (O(1))

Меняем удаляемый элемент на последний:
slice := []int{10, 20, 30, 40, 50}
slice[1] = slice[4] // [10, 50, 30, 40, 50]
newSlice := slice[:4] // [10, 50, 30, 40]


Использовать, когда нужна максимальная производительность и порядок не важен

Удаление с краёв слайса

Для первого элемента:
newSlice := slice[1:]


Для последнего элемента:
newSlice := slice[:len(slice)-1]


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍3👾2
Часто используют пустую структуру в качестве ключа контекста. Почему это лучше, чем просто взять строку

Дело в том, что строки как ключи контекста создают проблему конфликтов имён. Если несколько пакетов используют одну и ту же строку, например userID, они будут обращаться к одному и тому же значению в контексте. Это может привести к неожиданному перезаписыванию данных или к тому, что один пакет прочитает значение, которое установил другой.

Пустая структура решает это просто. Когда определяется type userContextKey struct{} в одном пакете и type userContextKey struct{} в другом, это два абсолютно разных типа с точки зрения компилятора. Они не конфликтуют, даже если имеют одинаковое имя, потому что существуют в разных пакетах.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7
Почему time.After в цикле может привести к утечке памяти и как это исправить

time.After создает таймер, который остается в памяти до истечения времени. Если вызывать это в цикле часто, таймеры накапливаются:
for {
select {
case event := <-ch:
handle(event)
case <-time.After(15 * time.Minute):
fmt.Println("timeout")
}
}


При большом потоке событий каждый цикл создает новый таймер на 15 минут, и они все висят в памяти одновременно. Это утечка.

Решение — использовать time.NewTimer и явно его останавливать:
timer := time.NewTimer(15 * time.Minute)
select {
case event := <-ch:
handle(event)
if !timer.Stop() {
<-timer.C
}
case <-timer.C:
fmt.Println("timeout")
}


timer.Stop() освобождает ресурсы.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🤔21
Что происходит с типом переменной в type switch при сравнении с nil

Когда вы используете type switch и ловите случай с nil, переменная примет тип исходного значения, которое вы проверяете. Не nil и не какой-то магический тип, а именно тот же тип, что и у интерфейса, с которым вы работаете.

Вот это не сработает:
var x any
var y error

switch t := x.(type) {
case nil:
y = t // Ошибка компиляции
}


Компилятор выругается, что any не может быть присвоен error, потому что any не имеет метода Error. Это подтверждает, что t внутри case nil имеет тип any, а не что-то другое.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥5
☝️ Уже сегодня: ИИ-агенты в продакшене — инженерный подход к интеграции LLM

Индустрия активно обсуждает потенциал нейросетей, способных автоматизировать бизнес-процессы и заменить целые отделы. Однако реальное внедрение агентов в production вскрывает серьёзные проблемы: разработчикам приходится бороться с непредсказуемыми галлюцинациями моделей, нестабильными API и сложной интеграцией в существующую архитектуру.

Сегодня в 19:00 МСК в рамках нашего курса «Разработка AI-агентов» мы проведём открытый вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке. Будем говорить о нейросетях с позиции жёсткой инженерии.

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

Тем, кто придёт на эфир, дадим промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
😁2
Часовая готовность: создаём ИИ-агента в прямом эфире

В 19:00 МСК в рамках нашего курса «Разработка AI-агентов» стартует вебинар «ИИ-агенты в продакшене: от хайпа к деньгам». Спикер — Полина Полунина, руководитель AI-направления в Альфа-Банке.

Будет live-демо работающего агента, реальные метрики из корпоративной среды и честный разбор архитектурных граблей — без воды и «успешного успеха».

Всем зрителям эфира дадим эксклюзивный промокод AGENTS на скидку 10 000 ₽ на любой тариф курса.

👉 Занять место на вебинаре
Что делает context.AfterFunc

context.AfterFunc планирует выполнение функции после завершения контекста — по отмене или таймауту. Функция запускается в новой горутине сразу после того, как ctx.Done() закрывается.

ctx, cancel := context.WithTimeout(parentCtx, 5*time.Second)
defer cancel()

context.AfterFunc(ctx, func() {
fmt.Println("Cleanup after context is done")
})


Типичные сценарии — очистка ресурсов, логирование, завершение фоновых операций.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6
Зачем может понадобиться context.WithoutCancel

context.WithoutCancel нужен, когда у вас есть операция, которая обязана завершиться независимо от того, был ли отменён родительский контекст.

Типичная проблема без него:
func handleRequest(ctx context.Context) {
doWork(ctx)
saveAuditLog(ctx) // ctx уже отменён — лог не запишется!
}


Когда клиент отключился или истёк таймаут, ctx отменяется, и все операции на нём падают с context.Canceled. Но некоторые вещи отменять нельзя.

Вот так это можно обойти:
func handleRequest(ctx context.Context) {
doWork(ctx)

safeCtx := context.WithoutCancel(ctx)
saveAuditLog(safeCtx) // выполнится в любом случае
}


WithoutCancel создаёт копию контекста, которая наследует values и deadline, но игнорирует отмену родителя.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
Что произойдёт, если вызвать context.AfterFunc на уже отменённом контексте

Функция выполнится немедленно в новой горутине, без ожидания. Проверять состояние контекста заранее не нужно, AfterFunc сам это обрабатывает.

ctx, cancel := context.WithCancel(context.Background())
cancel() // уже отменён

context.AfterFunc(ctx, func() {
fmt.Println("Runs immediately")
})


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Нужно ли лочить структуру мьютексом, если идёт конкурентная запись в разные поля

Короткий ответ — да. Структуры в Go не потокобезопасны по умолчанию. Даже если две горутины пишут в разные поля, без синхронизации возникает гонка данных.

type Data struct {
Field1 int
Field2 int
mu sync.Mutex
}

// горутина 1
d.mu.Lock()
d.Field1 = i
d.mu.Unlock()

// горутина 2
d.mu.Lock()
d.Field2 = i
d.mu.Unlock()


Мьютекс гарантирует, что в любой момент только одна горутина имеет доступ к структуре. Без него поведение программы непредсказуемо — go race detector это подтвердит.

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🤔81😢1🌚1
Самый востребованный навык в ИТ в 2026-м — навык создания ИИ-агентов

Мы полностью переработали курс «Разработка AI-агентов» под реалии 2026 года. Никакой долгой теории — с самого начала пишем код. Обучать и делиться набитыми шишками будут эксперты-практики из Газпромбанка, Альфа-Банка и других бигтехов.

В программе:

— архитектура автономных систем с тестированием, ReAct-циклами и контролем токенов;
— практическая работа с актуальными фреймворками LangGraph, AutoGen, MCP и CrewAI;
— настройка продвинутого RAG для парсинга документов и точного поиска;
— внедрение решений с учётом действующего законодательства (152-ФЗ);
— дипломная работа, за основу которой можно взять свой рабочий проект или задачу, которую предложим мы.

Эксперты поделятся инсайтами из реального продакшна — тем, о чём вам никогда не расскажет ни одна нейросеть.

Запись первого открытого вебинара, на котором мы вместе с руководителем AI-направления в Альфа-Банке Полиной Полуниной пилили агента в прямом эфире.


Ах да, чуть не забыли! Дарим промокод AGENTSWEB на скидку 10 000 рублей и два курса сверху при покупке до 15 марта 🎁

Стать AI-инженером
😁2
Что возвращает context.AfterFunc и как отменить запланированную функцию

AfterFunc возвращает функцию stop(). Если вызвать её до того, как коллбэк начал выполняться, он будет отменён.

stop := context.AfterFunc(ctx, func() {
// cleanup
})

if stopped := stop(); stopped {
fmt.Println("Callback cancelled before execution")
}


stop() возвращает true — функция остановлена до запуска.
stop() возвращает false — функция уже выполняется или была остановлена ранее.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍31
Что может остановить горутину

time.Sleep(d) — усыпляет горутину на нужное время. Классика, когда надо подождать.

runtime.Gosched() — временно приостанавливает текущую горутину и передаёт управление планировщику, чтобы другие горутины могли выполниться.

runtime.Goexit()
— завершает горутину немедленно, но аккуратно: все defer-ы выполнятся перед выходом.

Блокировка на канале — горутина ждёт, пока кто-то не отправит или не прочитает данные. Естественная синхронизация.

sync.Mutex — вызов Lock() блокирует горутину, пока мьютекс занят кем-то другим. Защита общих данных.

context.Context — горутина слушает ctx.Done() и останавливается, когда контекст отменяется или истекает таймаут.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👏4😁2😢1
Как вам вопросы прошедшей недели

Оцените их по шкале 🔥,❤️,👍,😢, 🥱,
где 🔥 — это супер, а 🥱 — это скучно.

Также приветствуется фидбек в комментах.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
11🔥10👍7
Что такое unique.Handle и зачем он нужен

unique.Handle[T] — это обёртка над значением типа T, которая гарантирует что два одинаковых значения всегда дадут один и тот же Handle. Это позволяет сравнивать значения через == вместо reflect.DeepEqual или побайтового сравнения.

import "unique"

h1 := unique.Make("hello")
h2 := unique.Make("hello")

fmt.Println(h1 == h2) // true — один и тот же указатель внутри


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥9
Кажется, мы окончательно перешли от игрушек к суровому AgentOps

Приглашаем на наш обновлённый курс по разработке ИИ-агентов. Никакой воды про «будущее нейросетей», только инженерный подход.

На курсе мы:

— пошагово строим готовые системы на LangGraph, CrewAI и MCP;
— настраиваем кэширование и роутинг, чтобы бот не сожрал токены;
— разбираемся со стейтом, учимся дебажить через time-travel и прикручиваем human-in-the-loop;
— выводим RAG в прод так, чтобы безопасники не завернули архитектуру из-за 152-ФЗ.

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

Кстати, на днях мы пилили агента в прямом эфире, если пропустили — есть запись вебинара.


Сегодня последний день, когда можно забрать курс по старым ценам. Базовый тариф сейчас стоит 49 000 ₽ (вместо 62 990 ₽), продвинутый трек — 99 000 ₽ (вместо 124 990 ₽). Если не хочется отдавать всю сумму сразу, есть рассрочка. Торопитесь — на потоке осталось всего 5 мест!

Зафиксировать цену и перейти к сборке своих агентов
2😁1
Почему GOPATH уступил место Go модулям

GOPATH просто брал тот код, что уже лежал на вашей машине. Склонировали проект на другом компьютере — и зависимости уже другие. Воспроизводимость сборки не гарантирована.

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👾1