«System Design — как темный лес. Go — вроде бы знаю, но знания поверхностные. А собеседование снова провавил на задаче по concurrency»
Знакомо?
Даже у разработчиков с 2-5 годами опыта остаются такие пробелы, которые мешают чувствовать уверенность:
– знаю много паттернов и приемов, но не знаю где и когда их применять;
– на System Design интервью не получается спроектировать систему за час;
– кажется, что понимаю Go, но только до тех пор, пока не столкнусь с задачами на собеседованиях.
🎓 В телеграм-канале Балун Владимир есть материалы, которые помогают прокачать Go и подготовиться к собеседованиям — без воды и пересказов статей из интернета.
1️⃣ Технические разборы:
– Итераторы в Golang
– Паттерны использования каналов в Go
– Внутреннее устройство аллокатора Go
– Внутреннее устройство мьютексов в Go и Linux
2️⃣ Подготовка к собеседованиям:
– Concurrency задачи с Go собеседований
– Решение сложных задач с Go собеседований
– Как подготовиться к System Design интервью
3️⃣ Карьера и опыт:
– Особенности Golang
– Карьера программиста в BigTech
– Путь от джуна до тимлида Яндекса
Если хочется разобраться в Go глубже, научиться объяснять сложные вещи и уверенно проходить собеседования — канал точно пригодится.
Автор канала - Владимир Балун. Разрабатывал высоконагруженные сервисы на С++ и Go в Тинькофф, Mail.ru и Ozon. Руководил командой распределенной трассировки запросов в Яндексе (11GB/s трафик) и провел больше ста технических интервью в разных компаниях. Сейчас создает образовательные проекты и делится опытом в телеграме.
Канал открыт. Без флуда. Только польза.
➡️Подписаться
Реклама. ИП Балун Владимир Николаевич. ИНН: 610111147548. Erid: 2VtzqwXyRqs
Знакомо?
Даже у разработчиков с 2-5 годами опыта остаются такие пробелы, которые мешают чувствовать уверенность:
– знаю много паттернов и приемов, но не знаю где и когда их применять;
– на System Design интервью не получается спроектировать систему за час;
– кажется, что понимаю Go, но только до тех пор, пока не столкнусь с задачами на собеседованиях.
– Итераторы в Golang
– Паттерны использования каналов в Go
– Внутреннее устройство аллокатора Go
– Внутреннее устройство мьютексов в Go и Linux
– Concurrency задачи с Go собеседований
– Решение сложных задач с Go собеседований
– Как подготовиться к System Design интервью
– Особенности Golang
– Карьера программиста в BigTech
– Путь от джуна до тимлида Яндекса
Если хочется разобраться в Go глубже, научиться объяснять сложные вещи и уверенно проходить собеседования — канал точно пригодится.
Автор канала - Владимир Балун. Разрабатывал высоконагруженные сервисы на С++ и Go в Тинькофф, Mail.ru и Ozon. Руководил командой распределенной трассировки запросов в Яндексе (11GB/s трафик) и провел больше ста технических интервью в разных компаниях. Сейчас создает образовательные проекты и делится опытом в телеграме.
Канал открыт. Без флуда. Только польза.
➡️Подписаться
Реклама. ИП Балун Владимир Николаевич. ИНН: 610111147548. Erid: 2VtzqwXyRqs
Please open Telegram to view this post
VIEW IN TELEGRAM
❤2👍1🔥1
😁3
ИТ-специалисты Петербурга, общий сбор
6 и 7 сентября пройдет ИТ-фестиваль «Сезон кода» для опытных разработчиков, ML-инженеров, архитекторов, специалистов по информационной безопасности и других ИТ-специалистов.
Спикеры из Т-Банка и других компаний зовут слушать доклады, обмениваться опытом и знакомиться с единомышленниками. Развлечения и музыка тоже будут.
В первый день:
— Разберетесь в архитектуре систем, надежности и работе с данными.
— Узнаете, как технологии помогают решать задачи клиентов и бизнеса.
— Поймете, как идеи становятся инструментами и продуктами.
Во второй день:
— Услышите про актуальные подходы к обеспечению информационной безопасности в разработке.
— Узнаете про backend-принципы, которые помогают работать эффективнее.
— Увидите, как работают LLM и куда все это движется.
Выбирайте один из дней или посетите оба. Встреча пройдет в новом ИТ-хабе Т-Технологий в Санкт-Петербурге.
Успейте зарегистрироваться до 5 сентября
6 и 7 сентября пройдет ИТ-фестиваль «Сезон кода» для опытных разработчиков, ML-инженеров, архитекторов, специалистов по информационной безопасности и других ИТ-специалистов.
Спикеры из Т-Банка и других компаний зовут слушать доклады, обмениваться опытом и знакомиться с единомышленниками. Развлечения и музыка тоже будут.
В первый день:
— Разберетесь в архитектуре систем, надежности и работе с данными.
— Узнаете, как технологии помогают решать задачи клиентов и бизнеса.
— Поймете, как идеи становятся инструментами и продуктами.
Во второй день:
— Услышите про актуальные подходы к обеспечению информационной безопасности в разработке.
— Узнаете про backend-принципы, которые помогают работать эффективнее.
— Увидите, как работают LLM и куда все это движется.
Выбирайте один из дней или посетите оба. Встреча пройдет в новом ИТ-хабе Т-Технологий в Санкт-Петербурге.
Успейте зарегистрироваться до 5 сентября
Forwarded from Golang вопросы собеседований
🔎 Задача на Go с подвохом
Код:
Вопрос: Что выведет этот код?
Варианты ответа:
A.
B.
C.
D.
Правильный ответ:B
Объяснение:
1. Создается срез с длиной 3 и capacity 4, заполненный значениями [1, 2, 3]
2. При передаче в функцию modifySlice:
— append добавляет элемент 4, но не вызывает переаллокацию
— Изменение s[0] = 100 применяется к тому же underlying массиву
3. Однако исходный срез в main() останется длины 3, но первый элемент изменится:
— Длина среза в main не меняется
— Но изменения элементов видны, так как используется тот же массив
@golang_interview
Код:
package main
import "fmt"
func main() {
s := make([]int, 3, 4) // Длина 3, capacity 4
s[0], s[1], s[2] = 1, 2, 3
modifySlice(s)
fmt.Println(s)
}
func modifySlice(s []int) {
s = append(s, 4)
s[0] = 100
}
Вопрос: Что выведет этот код?
Варианты ответа:
A.
[1 2 3]
B.
[100 2 3]
C.
[1 2 3 4]
D.
[100 2 3 4]
Правильный ответ:
Объяснение:
1. Создается срез с длиной 3 и capacity 4, заполненный значениями [1, 2, 3]
2. При передаче в функцию modifySlice:
— append добавляет элемент 4, но не вызывает переаллокацию
— Изменение s[0] = 100 применяется к тому же underlying массиву
3. Однако исходный срез в main() останется длины 3, но первый элемент изменится:
— Длина среза в main не меняется
— Но изменения элементов видны, так как используется тот же массив
@golang_interview
👍7❤3
🔎 Ищете способы улучшить работу с данными в Go?
На открытом вебинаре разберемся, как использовать итераторы для работы с большими данными. Поймем, что изменилось с Go 1.23 и какие преимущества дают ленивые итераторы.
❗️ Изучите, как заменить стандартные циклы на более эффективные итераторы и оптимизировать свой код. Освойте лучшие практики разработки на Go!
Присоединяйтесь к открытому уроку 19 августа в 20:00 МСК: https://otus.pw/VONw/?erid=2W5zFHaCSSC
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
На открытом вебинаре разберемся, как использовать итераторы для работы с большими данными. Поймем, что изменилось с Go 1.23 и какие преимущества дают ленивые итераторы.
❗️ Изучите, как заменить стандартные циклы на более эффективные итераторы и оптимизировать свой код. Освойте лучшие практики разработки на Go!
Присоединяйтесь к открытому уроку 19 августа в 20:00 МСК: https://otus.pw/VONw/?erid=2W5zFHaCSSC
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
❤1
Anonymous Quiz
46%
false false false false
20%
true true false false
9%
false false true true
25%
true true true true
👍4❤2
Команда Ozon Tech готовит мощнейший трек по бэкенду в рамках своей конференции E-CODE 💙
И это только одна из причин, почему стоит быть там 13-14 сентября. А ещё: качественный нетворк, 1х1 с топовыми IT-экспертами и HR, эксклюзивный мерч и интерактивы, вечеринки с участием НТР, Заточки, ILWT и Нейромонаха Феофана.
Успейте зарегистрироваться. Это обязательно⬅
И это только одна из причин, почему стоит быть там 13-14 сентября. А ещё: качественный нетворк, 1х1 с топовыми IT-экспертами и HR, эксклюзивный мерч и интерактивы, вечеринки с участием НТР, Заточки, ILWT и Нейромонаха Феофана.
Успейте зарегистрироваться. Это обязательно
Please open Telegram to view this post
VIEW IN TELEGRAM
🎯 Задача (Go, продвинутая конкуррентность; версия: Go 1.21+)
Сделай универсальную функцию обработки массива с контролем параллельности, сохранением исходного порядка результатов и мгновенной отменой при первой ошибке.
🟠 Требования:
- Сигнатура:
Process[T any, R any](ctx context.Context, in []T, worker func(context.Context, T) (R, error), parallelism int) ([]R, error)
- Параллельная обработка не более parallelism задач одновременно.
- Результаты возвращаются в том же порядке, что и входной срез, даже если отдельные задачи завершаются вразнобой.
- При первой ошибке:
- немедленно отменить все ещё выполняющиеся задачи,
- вернуть первую ошибку,
- не оставить «утекших» горутин.
- Учитывать ctx.Done() и корректно завершаться по таймауту/отмене.
- Без внешних зависимостей; только стандартная библиотека.
🟠 Подсказка:
- Используй context.WithCancelCause для распространения причины отмены.
- Организуй пул рабочих через буферизованный канал с задачами.
- Результаты складывай по индексу, чтобы сохранить порядок.
- Для потокозащищённой фиксации первой ошибки используй sync.Once.
Ниже — эталонная реализация и пример использования.
Код (Go 1.21+):
🟠 Как проверить:
- go run . — запусти несколько раз, чтобы увидеть разные порядки завершения, но стабильный порядок результатов.
- Поменяй порог ошибки в worker (например, x%3==0), чтобы убедиться, что отмена срабатывает мгновенно и горутины не висят.
- Проверь на гонки: go run -race .
Сделай универсальную функцию обработки массива с контролем параллельности, сохранением исходного порядка результатов и мгновенной отменой при первой ошибке.
- Сигнатура:
Process[T any, R any](ctx context.Context, in []T, worker func(context.Context, T) (R, error), parallelism int) ([]R, error)
- Параллельная обработка не более parallelism задач одновременно.
- Результаты возвращаются в том же порядке, что и входной срез, даже если отдельные задачи завершаются вразнобой.
- При первой ошибке:
- немедленно отменить все ещё выполняющиеся задачи,
- вернуть первую ошибку,
- не оставить «утекших» горутин.
- Учитывать ctx.Done() и корректно завершаться по таймауту/отмене.
- Без внешних зависимостей; только стандартная библиотека.
- Используй context.WithCancelCause для распространения причины отмены.
- Организуй пул рабочих через буферизованный канал с задачами.
- Результаты складывай по индексу, чтобы сохранить порядок.
- Для потокозащищённой фиксации первой ошибки используй sync.Once.
Ниже — эталонная реализация и пример использования.
Код (Go 1.21+):
package main
import (
"context"
"errors"
"fmt"
"math/rand"
"sync"
"time"
)
type job[T any] struct {
i int
val T
}
func Process[T any, R any](
parent context.Context,
in []T,
worker func(context.Context, T) (R, error),
parallelism int,
) ([]R, error) {
if parallelism <= 0 {
return nil, errors.New("parallelism must be > 0")
}
ctx, cancel := context.WithCancelCause(parent)
defer cancel(nil)
jobs := make(chan job[T], parallelism) // лёгкая обратная давление
out := make([]R, len(in))
var wg sync.WaitGroup
var once sync.Once
var firstErr error
// Рабочие
workerFn := func() {
defer wg.Done()
for {
select {
case <-ctx.Done():
return
case j, ok := <-jobs:
if !ok {
return
}
res, err := worker(ctx, j.val)
if err != nil {
once.Do(func() {
firstErr = err
cancel(err) // прерываем остальных
})
return
}
// Сохраняем порядок
out[j.i] = res
}
}
}
// Старт пула
wg.Add(parallelism)
for k := 0; k < parallelism; k++ {
go workerFn()
}
// Диспетчер задач
sendLoop:
for i, v := range in {
select {
case <-ctx.Done():
break sendLoop
case jobs <- job[T]{i: i, val: v}:
}
}
close(jobs)
// Ждём завершения
wg.Wait()
// Если была отмена по ошибке — вернём её
if firstErr != nil {
return nil, firstErr
}
// Если отменил родительский контекст — вернём его причину
if err := context.Cause(ctx); err != nil && !errors.Is(err, context.Canceled) && !errors.Is(err, context.DeadlineExceeded) {
// это cause из cancel(err), уже обработали выше
} else if err := context.Cause(parent); err != nil {
return nil, err
}
return out, nil
}
// Демонстрация: умножаем числа с случайной задержкой; каждое третье число — ошибка.
// Видно, что вывод упорядочен по входу, а отмена срабатывает на первой ошибке.
func main() {
rand.New(rand.NewSource(time.Now().UnixNano()))
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
input := []int{1, 2, 3, 4, 5, 6, 7}
parallelism := 3
worker := func(ctx context.Context, x int) (int, error) {
// эмуляция непредсказуемого времени работы
time.Sleep(time.Duration(rand.Intn(120)) * time.Millisecond)
if x%7 == 0 { // попробуй поменять условие на (x%3==0), чтобы увидеть раннюю отмену
return 0, fmt.Errorf("bad luck on %d", x)
}
select {
case <-ctx.Done():
return 0, ctx.Err()
default:
return x * x, nil
}
}
res, err := Process[int, int](ctx, input, worker, parallelism)
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("results:", res)
}
- go run . — запусти несколько раз, чтобы увидеть разные порядки завершения, но стабильный порядок результатов.
- Поменяй порог ошибки в worker (например, x%3==0), чтобы убедиться, что отмена срабатывает мгновенно и горутины не висят.
- Проверь на гонки: go run -race .
Please open Telegram to view this post
VIEW IN TELEGRAM
❤4👍2🔥2
23 августа Ozon Tech устраивает летнюю перезагрузку для backend-разработчиков на Go и C#.
GoSharp Weekend — это шанс прокачать скилы на реальных кейсах, познакомиться с командой разработки ведущего e-com и почиллить в историческом яхт-клубе в центре Москвы.
Эксперты Ozon Tech расскажут:
— как скорость работы приложения влияет на конверсию пользователей и что поможет ускорить ваши сервисы;
— как общий Helm chart, CI/CD и инструменты миграции позволяют быстро и стабильно менять конфигурации K8s в проде;
— как команда ушла от Ceph и построила своё устойчивое к высоким нагрузкам хранилище.
Успей забрать максимум от этого лета!
Участие бесплатное — подавай заявку и жди приглашения.
GoSharp Weekend — это шанс прокачать скилы на реальных кейсах, познакомиться с командой разработки ведущего e-com и почиллить в историческом яхт-клубе в центре Москвы.
Эксперты Ozon Tech расскажут:
— как скорость работы приложения влияет на конверсию пользователей и что поможет ускорить ваши сервисы;
— как общий Helm chart, CI/CD и инструменты миграции позволяют быстро и стабильно менять конфигурации K8s в проде;
— как команда ушла от Ceph и построила своё устойчивое к высоким нагрузкам хранилище.
Успей забрать максимум от этого лета!
Участие бесплатное — подавай заявку и жди приглашения.
👍3👎1
Anonymous Quiz
6%
data.val = <nil>
8%
data.val = 0
84%
data.val = 5
3%
data.val = undefined
😁3❤1👍1
🐹 Go error handling nuance
В стандартной библиотеке
оно не считает `ValueErrorType` и `*ValueErrorType` одним и тем же типом ошибки.
В отличие от него,
👉 Документация: https://docs.go101.org/std/pkg/go101.org/nstd.html#name-TrackErrorOf
Пример:
💡 Помни, что в Go T и *T — это разные типы, даже если они реализуют один интерфейс.
nstd.TrackErrorOf упрощает такие случаи и делает обработку ошибок гибче.
В стандартной библиотеке
errors.As
есть тонкость: оно не считает `ValueErrorType` и `*ValueErrorType` одним и тем же типом ошибки.
В отличие от него,
nstd.TrackErrorOf
из go101.org/nstd
обрабатывает оба варианта как одинаковые типы ошибок. 👉 Документация: https://docs.go101.org/std/pkg/go101.org/nstd.html#name-TrackErrorOf
Пример:
package main
import "errors"
type E struct{}
func (E) Error() string { return "" }
func main() {
e := &E{}
println(
errors.As(*e, &e), // false
errors.As(*e, e), // false
errors.As(e, e), // true
errors.As(e, &e), // true
)
}
💡 Помни, что в Go T и *T — это разные типы, даже если они реализуют один интерфейс.
nstd.TrackErrorOf упрощает такие случаи и делает обработку ошибок гибче.
❤3👍2
Тест для Golang-разработчиков, проверьте свои знания, готовы ли вы к обучению на курсе.
💻 Ответьте на 20 вопросов за 30 минут и проверьте, готовы ли вы к обучению на онлайн-курсе «Golang Developer. Professional» от OTUS. Сейчас Go становится все востребованнее, благодаря своей производительности, масштабируемости и экосистеме.
После 5 месяцев обучения вы сможете:
— Писать production-ready код, многопоточные и конкурентные программы.
— Понимать синтаксис и внутреннее устройство языка Go.
— Разворачивать микросервисы с помощью Docker.
— Проектировать и реализовывать микросервисную архитектуру на Go.
Также вас ждет прокачка навыков на реальных коммерческих кейсах и под руководством экспертов в этой области. Возможна рассрочка.
👉 ПРОЙТИ ТЕСТ: https://otus.pw/7SsF/?erid=2W5zFJ786Ak
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
💻 Ответьте на 20 вопросов за 30 минут и проверьте, готовы ли вы к обучению на онлайн-курсе «Golang Developer. Professional» от OTUS. Сейчас Go становится все востребованнее, благодаря своей производительности, масштабируемости и экосистеме.
После 5 месяцев обучения вы сможете:
— Писать production-ready код, многопоточные и конкурентные программы.
— Понимать синтаксис и внутреннее устройство языка Go.
— Разворачивать микросервисы с помощью Docker.
— Проектировать и реализовывать микросервисную архитектуру на Go.
Также вас ждет прокачка навыков на реальных коммерческих кейсах и под руководством экспертов в этой области. Возможна рассрочка.
👉 ПРОЙТИ ТЕСТ: https://otus.pw/7SsF/?erid=2W5zFJ786Ak
Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.
🧩 Хитрая задача по Go — «Пул, который не течёт, не зависает и сохраняет порядок»
Задача:
Реализуй обобщённую функцию MapOrdered — ограниченный по параллелизму пул воркеров, который применяет функцию
- не теряет отмену
- не допускает утечек горутин и зависаний,
- корректно обрабатывает
- поддерживает «раннее завершение» (как только достаточно результатов),
- обеспечивает backpressure (не раздувает буферы).
Сигнатуры:
Требования и тонкости
- Строгий порядок.
Выходные элементы должны соответствовать порядку поступления во input. Параллелизм допустим, но публикация результата — строго по индексу.
- Отмена и завершение.
- При отмене ctx функция должна без утечек завершить все горутины и закрыть выходной канал.
- Если EarlyStopN > 0, как только выдали N успешных результатов — корректно останавливаем обработку оставшихся задач (не зависаем, не «подвешиваем» воркеров).
🟠 Backpressure.
Никаких неограниченных буферов. Учитывай MaxInFlight, чтобы не переполнять память при медленном fn.
🟠 Panic-handling.
Если PanicAsError=true, паники из fn перехватываются и превращаются в error. Если false — паника должна «пробить» наружу (но без гонок и утечек).
🟠 Timeout на задачу.
При TaskTimeout>0 каждая задача исполняется с отдельным контекстом-дедлайном; таймаут — это ошибка задачи, а не общий стоп пула.
🟠 Гарантия отсутствия утечек.
После закрытия input и/или отмены контекста пул завершает все свои горутины. Проверь runtime.NumGoroutine() до/после и убедись в стабильном числе.
🟠 Без гонок.
Решение обязано проходить -race.
🟠 Zero-copy по возможности.
Не копируй большие данные лишний раз; не «складывай» всё в память — обрабатывай потоково. Допустимы минимальные накладные структуры (индексы, слоты).
Подсказки (но не решение)
- Для сохранения порядка пригодится «кольцо результатов» или слайс «слотов» с публикацией по индексу и «ползунком» выдачи.
- Отдельно продумай: кто закрывает выходной канал и когда (все задачи обработаны, или ранний стоп).
- Аккуратно обращайся с контекстами: каждому fn — свой дочерний ctx (для таймаутов), общий ctx — для остановки пула.
- Не забудь про range-variable capture в горутинах.
- Паники оборачивай через recover, если включён PanicAsError.
Задача:
Реализуй обобщённую функцию MapOrdered — ограниченный по параллелизму пул воркеров, который применяет функцию
fn
к входным элементам и отдаёт результаты строго в порядке входа, при этом:- не теряет отмену
context.Context
,- не допускает утечек горутин и зависаний,
- корректно обрабатывает
panic
внутри fn
,- поддерживает «раннее завершение» (как только достаточно результатов),
- обеспечивает backpressure (не раздувает буферы).
Сигнатуры:
type Result[R any] struct {
Value R
Err error
}
type Options struct {
Workers int // >0, число воркеров
MaxInFlight int // ≥ Workers, ограничение внутренних буферов
EarlyStopN int // если >0, остановиться после N успешных результатов
PanicAsError bool // если true, паники маппятся в error
TaskTimeout time.Duration // если >0, дедлайн на одну задачу
}
func MapOrdered[T any, R any](
ctx context.Context,
input <-chan T,
fn func(context.Context, T) (R, error),
opt Options,
) <-chan Result[R]
Требования и тонкости
- Строгий порядок.
Выходные элементы должны соответствовать порядку поступления во input. Параллелизм допустим, но публикация результата — строго по индексу.
- Отмена и завершение.
- При отмене ctx функция должна без утечек завершить все горутины и закрыть выходной канал.
- Если EarlyStopN > 0, как только выдали N успешных результатов — корректно останавливаем обработку оставшихся задач (не зависаем, не «подвешиваем» воркеров).
Никаких неограниченных буферов. Учитывай MaxInFlight, чтобы не переполнять память при медленном fn.
Если PanicAsError=true, паники из fn перехватываются и превращаются в error. Если false — паника должна «пробить» наружу (но без гонок и утечек).
При TaskTimeout>0 каждая задача исполняется с отдельным контекстом-дедлайном; таймаут — это ошибка задачи, а не общий стоп пула.
После закрытия input и/или отмены контекста пул завершает все свои горутины. Проверь runtime.NumGoroutine() до/после и убедись в стабильном числе.
Решение обязано проходить -race.
Не копируй большие данные лишний раз; не «складывай» всё в память — обрабатывай потоково. Допустимы минимальные накладные структуры (индексы, слоты).
Подсказки (но не решение)
- Для сохранения порядка пригодится «кольцо результатов» или слайс «слотов» с публикацией по индексу и «ползунком» выдачи.
- Отдельно продумай: кто закрывает выходной канал и когда (все задачи обработаны, или ранний стоп).
- Аккуратно обращайся с контекстами: каждому fn — свой дочерний ctx (для таймаутов), общий ctx — для остановки пула.
- Не забудь про range-variable capture в горутинах.
- Паники оборачивай через recover, если включён PanicAsError.
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1