Библиотека Go для собеса | вопросы с собеседований
رفتن به کانال در Telegram
Вопросы с собеседований по Go и ответы на них. Учиться у нас: clc.to/iEeaZw По рекламе: @proglib_adv Для обратной связи: @proglibrary_feeedback_bot Наши каналы: https://t.me/proglibrary/9197
نمایش بیشتر7 472
مشترکین
-124 ساعت
-47 روز
-2230 روز
آرشیو پست ها
❓ Как извлечь подстроку из строки
Строка в Go это неизменяемый срез байт. Поэтому подстрока берётся так же, как срез, но с одной оговоркой. Индексы считаются в байтах, а не в символах. На ASCII разницы не видно, на кириллице или эмодзи всё ломается.
Срез по байтам
s := "hello world"
fmt.Println(s[0:5]) // hello
fmt.Println(s[6:]) // world
Такой срез не копирует данные, он ссылается на тот же массив байт. Работает за O(1).
Теперь то же самое с кириллицей:
s := "привет"
fmt.Println(s[0:3]) // "пр"? нет, это "п" с хвостом
Каждая кириллическая буква в UTF-8 занимает два байта, так что s[0:3] разрежет символ пополам и вы получите битые данные.
Срез по символам
Если нужны именно символы, переводим строку в срез рун:
r := []rune("привет")
fmt.Println(string(r[0:3])) // при
Здесь уже есть аллокация и проход по всей строке, то есть O(n). Для длинных строк в горячем цикле это заметно.
🐸 Библиотека Go для собеса❓Как узнать, сколько элементов лежит в канале
Функция
len(ch) возвращает количество элементов, которые сейчас лежат в буфере канала. Функция cap(ch) возвращает вместимость буфера, то есть сколько элементов канал может хранить, не блокируя отправителя.
Пример с буферизированным каналом:
ch := make(chan int, 5)
ch <- 1
ch <- 2
fmt.Println(len(ch)) // 2
fmt.Println(cap(ch)) // 5
Для небуферизированного канала обе функции всегда дают ноль, потому что у него нет буфера, где данные могли бы задержаться.
ch := make(chan int)
fmt.Println(len(ch)) // 0
fmt.Println(cap(ch)) // 0
Значение len(ch) это снимок состояния на конкретный момент. Пока вы читаете результат и что-то с ним делаете, другая горутина уже могла записать или забрать элемент.
🐸 Библиотека Go для собеса🔥 Как перестать слепо доверять ИИ и начать им управлять?
1–2 августа на «ИИ-выходных» вы научитесь проектировать архитектуру автономных AI-агентов и контролировать их работу.
Что будет в вашем портфолио после обучения:
— Вы выйдете с готовым профилем AI-инженера (отлично дополнит ваши LinkedIn и GitHub).
— Освоите связку Python, FastAPI, OpenAI API, Docker и PostgreSQL.
— Соберете полноценный AI-сервис под вашу личную задачу.
Для кого: junior-middle разработчики. Вы пишете на Python, работаете с Git и терминалом (с нуля не подойдет, темп очень быстрый!).
👨💻 Спикер: Алексей Жиряков (Сбер, GenAI).
Места строго ограничены!
👉 Изучить программу и занять место
❓ Как узнать, что канал закрыт
Обычное
v := <-ch из закрытого канала не заблокируется и не паникует, а сразу вернёт нулевое значение типа.
Поэтому по одному v нельзя отличить «пришёл реальный ноль» от «канал закрыт и пуст — ровно как с мапой:
v := <-ch // 0 — но это может быть и настоящее значение, и признак закрытияВторой параметр решает вопрос: флаг
ok равен true, пока из канала можно прочитать отправленное значение, и становится false, когда канал закрыт и в нём не осталось буферизованных данных.
Важно, что закрытый канал сначала отдаёт всё, что в него успели записать, и только потом начинает возвращать false:
v, ok := <-ch
if !ok {
// канал закрыт и пуст
}
На практике за приёмом из канала обычно стоит range, который сам корректно завершается при закрытии — отдельная проверка ok не нужна:
for v := range ch {
// выполняется, пока канал не закрыт и не пустой
}❓ Как отличить отсутствующий ключ от нулевого значения в мапе
Через второй возвращаемый параметр при обращении к мапе — так называемый comma-ok. Обычное чтение
v := m[key] всегда вернёт значение: если ключа нет, это будет нулевое значение типа (0 для чисел, "" для строк, nil для указателей).
А значит, по одному только v нельзя понять, лежал ли там реальный ноль или ключа просто не было:
m := map[string]int{"a": 0}
v := m["a"] // 0 — но ключ есть
v = m["b"] // 0 — а ключа нет
Форма с двумя переменными решает это: второе значение — булев флаг, который равен true, только если ключ действительно присутствует в мапе. Именно на него и нужно смотреть, а не на само значение:
v, ok := m["a"]
if ok {
// ключ есть, v — реальное значение (даже если это 0)
}
_, ok = m["b"] // ok == false, ключа нет
Отсюда типичный идиоматичный паттерн — проверка и использование в одном if:
if v, ok := m[key]; ok {
// работаем с v
}
🐸 Библиотека Go для собеса📹 Из чего на самом деле состоит ИИ-агент?
Прикрепили для вас свежую вырезку из вебинара. Внутри, что прячется под капотом агентных систем: от LLM-ядра до вызова внешних инструментов. Обсуждаем, какими бывают агенты (спойлер: далеко не только автономными) и когда какой подход использовать.
Готовы перейти от видео к практике и собрать свой первый продакшн-кейс?
Прямо сейчас у нас действует акция «3 курса по цене 1»:
🔹 При покупке VIP-тарифа нового потока «Разработка ИИ-агентов» вы получаете в подарок хардкорный курс «AgentOps» + ещё один любой курс Академии на ваш выбор! 🔹 Ваша чистая экономия — 129 000 ₽! Два топовых курса по созданию и контролю агентов обойдутся вам всего в 134 000 ₽ вместо 263 000 ₽. Плюс третий курс бонусом (например, «Математика для AI»).Сомневаетесь, подойдет ли вам формат? Оставьте заявку и пройдите бесплатный демо-урок, чтобы протестировать платформу перед покупкой. 👉 Пройти демо-урок и забрать 3 курса по цене 1
❓ Освободится ли память после
bigSlice = bigSlice[:5]
Нет, не обязательно. Операция [:5] создаёт новый слайс-заголовок с длиной 5, но он по-прежнему указывает на тот же самый underlying array. Пока хотя бы один слайс ссылается на этот массив, сборщик мусора не может его освободить. То есть даже если нам нужны первые 5 байт, за спиной может «висеть» все 10 MB:
Дело в том, что срез — это лишь тройка из указателя на массив, длины и ёмкости. Урезание длины меняет только заголовок и никак не влияет на память под ним. Capacity нового слайса по-прежнему указывает на конец исходного массива, поэтому GC считает его достижимым.
Чтобы отдать большой массив сборщику, нужные данные копируют в новый, компактный слайс, а ссылку на исходный обнуляют:
smallCopy := make([]byte, len(smallSlice))
copy(smallCopy, smallSlice)
bigSlice = nil
Тот же эффект короче — через append в nil-слайс, который выделит свежий массив под реальный объём данных:
smallCopy := append([]byte(nil), smallSlice...)
🐸 Библиотека Go для собеса💰 Почему одним Data Scientist платят больше, чем другим?
Дело не только в знании Python и ML-библиотек. Во многих компаниях уровень специалиста оценивают по математической подготовке: теории вероятностей, статистике, линейной алгебре и математическому анализу.
Именно эти знания помогают понимать модели, решать более сложные задачи и претендовать на позиции с более высокой оплатой.
На курсе «Математика для Data Science» вы изучите разделы, которые используются в работе Data Scientist и ML Engineer.
Что вас ждёт:
🔹 40+ видеолекций и 150+ практических заданий на Python
🔹 Проверка домашних работ и обратная связь от преподавателей
🔹 Подготовка к техническим собеседованиям
🔹 Программа от преподавателей ВМК МГУ, НИУ ВШЭ и экспертов индустрии
👉 Записаться на бесплатный демо-урок
❓ Нужно ли создавать новый
http.Client на каждый запрос
Нет. Client и его Transport безопасны для конкурентного использования и держат пул TCP соединений. Новый клиент на каждый запрос убивает keep alive, каждый вызов будет заново устанавливать соединение вместе с TLS рукопожатием.
Правильно создать один клиент на приложение и задать ему тайм аут, потому что у http.DefaultClient его нет.
🐸 Библиотека Go для собеса❓ Что означает гарантия «фиксеры не должны менять поведение вашей программы»
Это про автоматические исправления кода — фиксеры (например,
go fix, gofmt, suggested fixes из go vet / analysis-фреймворка, или --fix в линтерах вроде golangci-lint). Гарантия говорит, что такой фикс меняет только форму кода, но не его поведение во время выполнения.
Под поведением тут понимается наблюдаемая семантика: что программа возвращает, какие у неё сайд-эффекты — запись в файл, вызовы по сети, вывод, — как идёт control flow, какие ошибки и паники она порождает. То есть на тех же входных данных до и после фикса программа должна давать тот же результат и те же эффекты. Трансформация behavior-preserving, семантически нейтральная.
Пример: фиксер может переписать устаревший API на новый, переставить импорты через goimports, отформатировать код — но не должен, скажем, изменить условие в if так, что поменяется ветвление.
И тут ключевой момент — формулировка «should not», а не «will not». Это заявленное свойство по дизайну, а не строгая гарантия на все случаи. В Go, где есть интерфейсы, рефлексия, горутины и гонки, всегда найдётся пограничный кейс, где формально эквивалентная замена всё же меняет смысл. Поэтому на практике фиксы обычно делят на safe и unsafe: safe можно катить массово, unsafe применяют осознанно.
🐸 Библиотека Go для собеса❓ Почему
http.ListenAndServe(":8080", nil) считается плохой практикой
nil означает DefaultServeMux, глобальный роутер. В него может зарегистрировать хендлер любой импортированный пакет, например net/http/pprof делает это в init. Так наружу случайно утекают отладочные ручки.
У такого сервера нет тайм аутов. Правильнее создать свой Server и свой ServeMux.
Правильный вариант:
srv := &http.Server{
Addr: ":8080",
Handler: mux,
ReadHeaderTimeout: 5 * time.Second,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
IdleTimeout: 120 * time.Second,
}
log.Fatal(srv.ListenAndServe())
🐸 Библиотека Go для собеса🎬 Как ИИ ускоряет разработку и где ломаются архитектуры
Мы провели открытый вебинар, где разобрали реальные боли проектирования автономных систем. Ольга Лукьянова на практическом кейсе показала, как использовать ИИ-ассистентов для реальных задач. Вы просили запись встречи — она уже в открытом доступе!
Что внутри:
— Как с помощью ИИ быстрее разбираться в незнакомом коде и готовить пулл-реквесты;
— Критерии выбора между одним агентом и мультиагентной системой;
— Разбор популярных архитектурных ошибок и ограничений современных ИИ;
— Практические рекомендации по проектированию и внедрению облачных агентов.
👉 Посмотреть полную запись можно тут:
● VK
● YouTube
🚀 Хотите пойти дальше открытого вебинара? Если вы готовы перейти от простых промптов к проектированию надежных, отказоустойчивых ИИ-систем, которые не сливают бюджет компании на API, приходите на курс AgentOps. Поток уже стартовал, но двери еще приоткрыты!
👉 Успеть на курс AgentOps
❓ Как работает iota в блоке констант
iota начинает с нуля в начале блока const и увеличивается на единицу для каждой новой строки. После присвоения значения переменной, можно не указывать iota снова для следующих переменных, и Go самостоятельно применит инкремент.
const (
A = iota
B
C
D
)
// A = 0, B = 1, C = 2, D = 3
Важно помнить, что iota применяется только внутри блока const. Если создать второй блок const, то счетчик снова начинает с нуля. Каждый блок независим.
🐸 Библиотека Go для собеса🎮 Планы на выходные: соберите ИИ-агента в нашей новой игре!
Запустили интерактивную аркаду, где вы на практике поймете, как устроены агентные системы.
Юзеры бомбят в чате, тикеты горят, вам нужно спасать прод 🤓. Выстраивайте граф агента, подключайте узлы (RAG, CRM, Guardrails) и принимайте решения на развилках, чтобы бот не сливал данные.Какие навыки проверите: - Архитектура: сборка графов на LangGraph; - Компоненты: интеграция LLM, RAG и памяти; - Безопасность: настройка Guardrails и отладка ошибок; - Стейт: логика на сложных развилках. Бонус: Больше баллов — выше скидка на обучение! Наш новый поток стартует 14 июля. При покупке курса вы забираете еще 2 любых курса Академии в подарок! Протестируйте свою инженерную логику и заберите максимальную скидку на обучение. 👉 Сыграть в аркаду и выбить скидку
❓ Чем
Handler отличается от HandlerFunc
Handler это интерфейс с одним методом ServeHTTP(ResponseWriter, *Request). HandlerFunc это тип функции, у которого метод ServeHTTP уже реализован и просто вызывает саму функцию. Он нужен как адаптер, чтобы обычную функцию можно было отдать туда, где ждут интерфейс.
mux.Handle("/ping", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("pong"))
}))
🐸 Библиотека Go для собеса👣 Многие разработчики приходят в Go с багажом паттернов из Java и C#. В результате простой и понятный код постепенно обрастает слоями абстракций, лишними интерфейсами и десятками DTO, которые усложняют поддержку проекта.
🗓 8 июля в 20:00 МСК приглашаем вас на открытый урок в преддверии старта курса «Go-разработчик. Продвинутый уровень». На занятии разберём, почему привычные подходы из других языков не всегда работают в Go, как выстроить архитектуру через Handler → Service → Repository без циклических зависимостей, где действительно нужны интерфейсы и как избежать избыточных абстракций.
❗️Вы узнаете, какие ошибки чаще всего встречаются на проверках кода, научитесь проектировать приложения с понятным разделением ответственности и поймёте, как писать код, который останется читаемым и через полгода.
➡️ Регистрируйтесь и познакомьтесь с подходом, который помогает писать на Go проще, надёжнее и профессиональнее: https://clc.to/kpNJbw
Реклама. ООО «Отус онлайн-образование», ОГРН 1177746618576, www.otus.ru
ОПРОС: Ответьте на пару вопросов и получите промокод на все наши курсы! 🎁
Команда Prоglib.аcаdemy готовит к запуску новые продукты, и нам нужна ваша помощь. Мы хотим создавать обучение, которое будет решать ваши реальные карьерные задачи и бить точно в цель.
Поделитесь своим опытом и ожиданиями, чтобы мы сделали наши курсы еще полезнее именно для вас! Заполнение анкеты займет буквально 2–3 минуты, а с нас — скидка на любой наш курс!
👉 Пройти опрос в Яндекс Формах и забрать промокод
❓ Что такое голый
return и когда он опасен
Это return без перечисления значений при именованных возвратах. В коротких функциях он читается нормально, но в длинных мешает понять, что именно вернётся, потому что значения задаются где то выше по телу. Поэтому голый возврат держат для небольших функций.
🐸 Библиотека Go для собеса⚠️ Уже завтра стартует курс AgentOps!
Мы собрали на потоке сборную из мастеров IT-рынка. Практики из BigTech научат вас контролировать и отлаживать ИИ-агентов, чтобы они работали предсказуемо и не сливали бюджет на API.
🔥 Заберите 3 курса по цене 1:
● При покупке VIP-тарифа (осталось 4 места) нового потока «Разработка ИИ-агентов» получаете в подарок курс «AgentOps» + ещё один любой курс Академии (например, «Математика для разработки AI», чтобы глубже освоить направление). ● Три курса обойдутся вам всего в 134.000 ₽ вместо 263.000 ₽. ● Доступна удобная беспроцентная рассрочка, платеж можно разбить на несколько комфортных частей.Хотите прокачать свое портфолио продакшн-кейсом, но пока сомневаетесь? Пройдите наш бесплатный демо-урок, чтобы протестировать формат перед покупкой. 👉 Забрать 3 курса по цене 1 и получить демо-урок
❓ Какой самый распространённый паттерн множественного возврата
Пара значение и ошибка. Функция возвращает результат и
error, который вызывающий код обязан проверить. Это основа идиоматичной обработки ошибок в Go.
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("деление на ноль")
}
return a / b, nil
}
🐸 Библиотека Go для собеса