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

Учиться у нас: clc.to/iEeaZw

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

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
Можно ли присвоить int переменной типа int64 без преобразования

Нет. Это разные типы, даже если на текущей платформе они одного размера. Неявных числовых преобразований в Go нет, нужна явная конверсия int64(x).

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Как найти два числа с заданной суммой за O(n)

Наивное решение это два вложенных цикла и O(n²). Оптимальное использует map. Для каждого элемента вычисляем complement = target - s[i] и смотрим, есть ли он уже в map. Если есть, нашли пару. Если нет, кладём текущий элемент в map и идём дальше.

func twoSum(nums []int, target int) (int, int) {
seen := make(map[int]int) // значение -> индекс
for i, v := range nums {
if j, ok := seen[target-v]; ok {
return j, i
}
seen[v] = i
}
return -1, -1
}


Сначала ищем complement в map, только потом добавляем текущий элемент. Это защищает от ложного совпадения с самим собой при target = 2 * v.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
3🔥1
Что произойдёт при переполнении целого числа

При переполнении целого числа в Go значение не вызывает ошибку, а «переворачивается» внутри допустимого диапазона. Это поведение называется wrap-around: если значение превышает максимальное, оно продолжает отсчёт с минимального значения, и наоборот.

Поэтому переполнение нужно ловить проверками вручную. В константном выражении компилятор поймает его на этапе сборки, а в рантайме нет.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
Как сдвинуть срез на k позиций вправо

Есть несколько подходов. Самый элегантный через три разворота. Разворачиваем весь срез, потом первые k элементов, потом оставшиеся. Три операции, каждая O(n), итого O(n). Память O(1).

func rotate(s []int, k int) {
n := len(s)
k = k % n
rev := func(a []int) {
for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
a[i], a[j] = a[j], a[i]
}
}
rev(s)
rev(s[:k])
rev(s[k:])
}


k % n обязателен: если k >= n, сдвиг зацикливается. Без этого для k = n мы получим обратный срез вместо исходного.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥1🥱1
У вас двунаправленный gRPC-стрим. Сервер пишет данные быстрее, чем клиент читает. Какой подход позволяет корректно обработать эту ситуацию без преждевременного обрыва соединения

time.Sleep — антипаттерн: вы не знаете нужную задержку заранее, и это не масштабируется.

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

Рядом с буферизованным каналом обычно стоят ещё два инструмента. Контекст с дедлайном нужен чтобы не ждать вечно зависшего клиента. Тикер — для периодических keepalive-пингов, чтобы убедиться, что соединение живо и клиент на том конце вообще ещё читает.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4
📊 Хотите войти в Data Science, но математика кажется самым сложным этапом?

На практике большинство джунов спотыкаются не о Python, а о математическую базу:

▪️ Теорию вероятностей и статистику
▪️ Линейную алгебру
▪️ Математический анализ
▪️ Комбинаторику

Именно на этих темах строятся машинное обучение, аналитика данных и рекомендательные системы.

Освойте ключевые разделы математики, которые используются в Data Science и Machine Learning на курсе «Математика для Data Science».

Что вас ждет:

🔹 40+ видеолекций и 150+ практических заданий на Python
🔹 Проверка домашних работ и обратная связь от преподавателей
🔹 Подготовка к задачам с технических собеседований
🔹 Программа от преподавателей ВМК МГУ, НИУ ВШЭ и экспертов индустрии

Курс подойдет разработчикам, аналитикам и всем, кто планирует развиваться в Data Science и Machine Learning.

👉 Записаться на бесплатный демо-урок
Чем отличается деление на ноль для целых чисел и для float

Для целых типов деление на ноль — это паника. Программа сразу падает с ошибкой division by zero, потому что результат такой операции в рамках целочисленной арифметики не определён.

Для float32 / float64 деление на ноль допустимо и подчиняется стандарту IEEE 754. Вместо ошибки получаются специальные значения: +Inf, -Inf, Nan.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🤔1
Что такое sliding window и когда его применять

Sliding window это приём для задач, где нужно найти подмассив или подстроку, удовлетворяющие условию. Вместо перебора всех пар (i, j) за O(n²) мы поддерживаем окно с двумя границами и двигаем их по условию.

Приём подходит, когда нужно найти минимальную или максимальную длину подмассива с суммой >= target, найти подстроку без повторяющихся символов, найти все анаграммы паттерна в строке. Окно бывает фиксированного размера или динамическим.

// минимальный подмассив с суммой >= target
func minSubarrayLen(target int, nums []int) int {
left, sum, res := 0, 0, len(nums)+1
for right := range nums {
sum += nums[right]
for sum >= target {
if right-left+1 < res {
res = right - left + 1
}
sum -= nums[left]
left++
}
}
if res == len(nums)+1 {
return 0
}
return res
}


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Почему большой int64 может исказиться при разборе JSON

JSON по спецификации не имеет строгих типов
int32/int64 — там есть только number, а в Go при разборе encoding/json число сначала парсится в float64, если не указан конкретный тип.

Есть несколько решений:

Использовать строки для больших чисел:
{"id": "9223372036854775807"}


Использовать
json.Decoder.UseNumber():
dec := json.NewDecoder(r)
dec.UseNumber()


Кастомный Unmarshal

Читать как json.Number и вручную конвертировать в int64

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5
💻 3 курса по цене одного — собери стек для оффера в топовую IT-компанию

Для следующего карьерного шага мало писать код. Работодатели ждут не только знания языка, но и понимания архитектуры, алгоритмов, автоматизации, AI-инструментов и агентных систем.

Одно направление закрывает только часть задачи.

Поэтому сейчас мы предлагаем освоить сразу несколько востребованных навыков — выбери любой курс и получи доступ еще к двум бесплатно 🔥

Собери стек навыков под свою цель:

🔹 подготовка к сильным компаниям (алгоритмы, архитектура);
🔹 переход в AI-направление (ИИ-агенты, AgentOps);
🔹 развитие в ML и Data Science (математика, основы ML);
🔹 новый оффер и рост дохода.

Полученные знания применяешь в работе уже во время обучения.

Акция действует 48 часов — 13 и 14 июня.

👉 Переходи на сайт, выбирай курсы и оставляй заявку — за 10 минут поможем собрать комплект под твою цель.
Как объединить два отсортированных среза в один

Классическая операция из mergesort. Заводим три указателя: i для a, j для b, k для результата. Сравниваем текущие элементы обоих срезов и берём меньший. После того как один из срезов закончился, дописываем остаток другого.

func mergeSorted(a, b []int) []int {
res := make([]int, 0, len(a)+len(b))
i, j := 0, 0
for i < len(a) && j < len(b) {
if a[i] <= b[j] {
res = append(res, a[i])
i++
} else {
res = append(res, b[j])
j++
}
}
res = append(res, a[i:]...)
res = append(res, b[j:]...)
return res
}


a[i:]... добавляет хвост одной операцией без лишнего цикла. Сложность O(n + m) по времени, O(n + m) по памяти на результат.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
Какого типа результат len и можно ли индексировать срез значением int64

len и cap возвращают int, индексы тоже имеют тип int. Индексировать срез значением int64 напрямую нельзя, нужна конверсия к int. Из-за этого длина среза ограничена размером int на платформе.

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

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

🚀 30 июня стартует курс «Разработка ИИ-агентов».

До 20 июня действует сниженная цена.

За 8 недель под руководством практиков из бигтеха вы соберёте собственного AI-агента, который работает с API, использует память, подключается к внешним сервисам и решает реальную задачу.

Что разберём:

🔹 архитектуру AI-агентов и надёжный вывод;
🔹 LangGraph и оркестрацию workflow;
🔹 MCP и работу с внешними инструментами;
🔹 RAG-системы;
🔹 AgentOps, observability и evals;
🔹 безопасность и защиту от prompt injection;
🔹 мультиагентные системы и A2A.

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

👉 Узнать программу и забронировать место со скидкой
У вас есть map[int]Record. Несколько горутин читают и пишут в него одновременно. Что произойдёт

Go рантайм с версии 1.6 содержит детектор конкурентных записей в map. При одновременной записи из нескольких горутин программа завершится с паникой concurrent map writes — намеренно, чтобы не допустить повреждения данных.
 
Но детектор срабатывает не всегда: он вероятностный. Поэтому полагаться на него как на защиту нельзя.
 
Правильные решения в зависимости от нагрузки: sync.RWMutex вокруг map, sync.Map для случаев с редкими записями и частыми чтениями, или шардирование — несколько map с отдельными мьютексами.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
Разработчик создаёт time.NewTicker внутри цикла и забывает вызвать ticker.Stop(). Что произойдёт

time.NewTicker регистрирует таймер в runtime heap таймеров. Раньше GC не собирал тикеры автоматически — они жили, пока не будет вызван Stop().

Начиная с Go 1.23 ситуация изменилась: garbage collector теперь может собирать неиспользуемые тикеры, если на них больше нет ссылок. То есть забытый Stop() больше не гарантирует утечку памяти.

⚠️ Важно

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

Это по-прежнему может проявляться как постепенный рост потребления памяти и деградация производительности под нагрузкой — просто теперь причина не всегда в самом факте отсутствия Stop(), а в удержании ссылок.

Как это поймать

go tool pprof с профилем goroutines покажет горутины, заблокированные на чтении из каналов тикеров. Heap-профиль может показать рост объектов, связанных с таймерами.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥 Чем больше агентов — тем лучше? Не всегда. Уже завтра поговорим о реальных ограничениях на открытом уроке «Мультиагентные системы: почему большинство архитектур переусложнены».

Спикер — Дмитрий Юдин, руководитель AI/ML-направления в Сloud․ru.

После урока вы:

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

🗓️ 18 июня, 19:00 (МСК)
⏱️ 90 минут

👉 Зарегистрироваться и получить промокод на 10 000 ₽
Чем io.EOF отличается от io.ErrUnexpectedEOF? В каком случае Read должен возвращать EOF, а в каком — ErrUnexpectedEOF

io.EOF — сигнал о штатном конце данных. Read возвращает его когда источник исчерпан и больше нечего читать. Это не ошибка в смысле «что-то пошло не так» — это нормальное завершение потока.

По спецификации io.Reader, EOF может прийти либо вместе с последними байтами (n > 0, err == io.EOF), либо отдельным вызовом (n == 0, err == io.EOF). Оба варианта корректны — поэтому правильный код всегда сначала обрабатывает прочитанные байты, потом проверяет ошибку.

io.ErrUnexpectedEOF — сигнал о том, что поток закончился в неожиданном месте. Источник данных иссяк раньше, чем ожидалось по протоколу или по запросу.

Типичный пример — io.ReadFull. Функция просит ровно len(buf) байт. Если источник вернул EOF до того, как буфер заполнен, ReadFull транслирует это в ErrUnexpectedEOF.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥2
Уже сегодня в 19:00 (МСК) стартует открытый урок!

Тема:

«Мультиагентные системы: почему большинство архитектур переусложнены»


🔥 За 90 минут разберёмся, когда действительно стоит строить мультиагентную систему, а когда она только добавляет сложность, расходы и новые точки отказа.

Поговорим о критериях выбора архитектуры, типичных ошибках и ограничениях современных ИИ-агентов, которые важно учитывать ещё до внедрения в продукт.

🎙️ Спикер — Дмитрий Юдин, руководитель AI/ML-направления в Сloud․ru.

🎁 Для всех участников подготовили промокод на скидку 10 000 ₽ на курс «Разработка ИИ-агентов».

👉 Успей присоединиться к уроку
Вам нужно итерироваться по map[string]int и получать элементы всегда в одном и том же порядке. Какой подход использовать

Порядок итерации по map в Go намеренно рандомизирован с версии 1.0. Это сделано специально, чтобы разработчики не полагались на порядок как на гарантию.
 
Надёжный способ: keys := make([]string, 0, len(m)) → заполнить ключами → sort.Strings(keys) → итерироваться по слайсу, читая значения из map.
 
Отдельный вопрос со звёздочкой: если ключи — числа, а не строки, тип ключа влияет на аллокации при сортировке. []int с sort.Ints не аллоцирует лишнего, тогда как конвертация в []interface{} для универсальной сортировки создаёт нагрузку на GC при большом количестве элементов.

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

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

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

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

copy копирует элементы из исходного слайса в целевой и возвращает число скопированных элементов. Это число равно минимуму из len(dst) и len(src). Лишние элементы источника просто игнорируются, ошибки не будет.

src := []int{1, 2, 3, 4}
dst := make([]int, 2)
n := copy(dst, src)
fmt.Println(n, dst) // 2 [1 2]


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