Вы находитесь на странице: 1из 5

Вопросы для собеседования Golang разработчика | by Viktor Ugolnikov

Общие вопросы

Что происходит, когда я вбиваю в адресную строку моего браузера medium.com? Как запрос доходит до
сервера, и как идет обратно? Гранулярность — настолько маленькая, насколько возможно.
1. Парсинг строки запроса - получаем протокол, хост, ресурс, параметры запроса
2. Хост необходимо преобразовать в IP-адрес - браузер обращается к своему DNS-кэшу, DNS-кэшу ОС,
файлу hosts… Так или иначе мы резолвим хост в IP
3. Пусть это будет http запрос - сформируется GET запрос, добавятся куки при необходимости,
заголовки, хост, адрес/ресурс, параметры, тело запроса. На уровне приложения дальше будет идти
речь просто о взаимодействии по http
4. Этот запрос упакуется в tcp сегмент, средствами ОС установится tcp-соединение, начнется обмен
данными по http
5. Сервер примет запрос, вернет некий ответ (страницу + данные), браузер отобразит это пользователю

В чем отличие протоколов TCP и UDP? В каком случае UDP предпочтительнее?


TCP устанавливает соединение, гарантирует целостность и порядок сегментов
UDP просто отсылает данные
Первый нужен там, где необходима надежность обмена данными (чат, передача данных)
Второй используется при передаче избыточных данных, например видео и голосовой информации в онлайн
режиме

Можно ли убить поток внутри определенного процесса командой kill?


Команда kill завершает весь поток, нет

Как можно отсортировать файл на 100GB, в котором расположены числа в случайном порядке, по 1 числу
на строку? Ограничения — объем ОЗУ на машине составляет 1GB.
Самый распространенный ответ гугла - разбиение на доступные по памяти куски, сортировка, далее слияние
отсортированных кусков.

Какая твоя любимая технология (это может быть БД, сервер очередей, библиотека — что угодно)? А
почему?
Нет, я просто делаю задачи от ПМ-а и тимлида)))

Какие решения ты бы принял, будучи техническим директором на своем текущем/прошлом месте


работы?
Менял бы технологии/библиотеки на второстепенных/новых небольших проектах, выделял бы больше
времени на закрытие техдолга, напряг бы кого-то, чтобы привести документацию к API в порядок

Какую тему ты бы сам хотел обсудить?


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

Что, по твоему, такое микросервисы?


Микросервисы - также известные как микросервисная архитектура - это архитектурный стиль, который
структурирует приложение как набор сервисов, которые

- Легко обслуживается и тестируется


- Слабо связанный
- Независимое развертывание
- Организован вокруг бизнес-возможностей
- Принадлежит небольшой команде

Какие преимущества ты видишь у микросервисной архитектуры по сравнению с монолитом? А какие


недостатки?
+:
- Более быстрый деплой
- Возможность использовать разные технологии в одном проекте
- Проще рефакторить
- Можно масштабировать только нужный функционал
- Проще ввести нового сотрудника в работу

-:
- Труднее тестировать и запускать приложение в целом
- Необходимость заботиться о надежной коммуникации между микросервисами
- Сложность с транзакциями в БД

С какими трудностями ты сталкивался в построении микросервисной архитектуры?


Не работал с микросервисами

Что ты использовал (или о чем слышал) для трассировки сервисов? Для мониторинга? А для
логирования?
Слышал и немного использовал прометей, графану, логи вроде в кибане были (бла-бла, тут просто у меня
нет реального опыта)

Как быть с консистентностью данных между несколькими микросервисами?


Хз)))
Вопросы по языку Golang
1. Что из себя представляет тип данных string в языке Golang? Можно ли изменить определенный символ
в строке? Что происходит при склеивании строк?
string это некоторая абстракция над массивом byte (uint8), но с особенностями - нельзя менять элементы
этого массива при помощи доступа по индексу. Единичные символы в го принято обрабатывать при помощи
rune (int32, 'c' - для хранения UTF-кода любого символа этого хватит), руны связаны со строками в том
смысле, что если, к примеру, для доступа к символам строки использовать for range, то перебор будет
именно по рунам, а не по байтам, некоторые руны могут занимать более одного байта. При склеивании строк
выделяется новая область памяти под массив байт и туда пишется результат.
https://hermanschaaf.com/efficient-string-concatenation-in-go/

2. Вытекающий вопрос — как эффективно склеивать множество строк?


Поиском в гугле ответа на этот стандартный вопрос я нашел, что самый эффективный способ этот
strings.Join, почти не отличается от способа с записью байтов в bytes.Buffer
https://hermanschaaf.com/efficient-string-concatenation-in-go/

3. Что будет происходить при конкурентной записи в map? Как можно решить эту проблему?
Возможна паника/гонки при одновременном доступе к одному полю мапы, поэтому стоит использовать
мьютексы, например, из пакета sync.

4. Нужно ли лочить структуру мьютексом, если идет конкурентная запись в разные поля структуры?
Из соображений безопасности можно этого не делать, а в целях быстродействия - стоит.
https://stackoverflow.com/questions/29496605/is-it-thread-safe-to-access-different-members-of-struct-in-go

5. Что выведет код?

func main() {
runtime.GOMAXPROCS(1)

done := false

go func() {
done = true
}()

for !done {
}
fmt.Println("finished")
}
Будет лок
Как можно изменить этот код, чтобы был вывод “finished”?
Убрать ограничение на 1 процессор или увеличить.

6. Как устроены каналы “под капотом”?


Под капотом Golang — как работают каналы. Часть 1. | by Viktor Ugolnikov
Строение каналов в Golang. Часть 2. | by Viktor Ugolnikov

(пишу по памяти)
Канал внутри представлен структурой hchan, в ней есть поля:
buf
bufSize
bufQnt
указатель на позицию в буфере на запись
указатель на позицию в буфере на чтение
closed
список горутин на запись (представлены структурой sudog {elem, g})
список горутин на чтение (представлены структурой sudog {elem, g})
тип данных в канале
размер единицы данных в канале
мьютекс для блокировки вышеописанных полей при чтении/записи

7. Какая есть проблема в коде?


var counter int
for i := 0; i < 1000; i++ {
go func() {
counter++
}()
}
Гонки

Как её можно решить?


Использовать мьютекс

А как её можно бы было решить, если бы в языке не было пакета sync?


Закостылить на канале, т.к. там внутри есть мьютекс https://play.golang.org/p/HezTfBXy3bj

8. Можно ли реализовать sync.Mutex и sync.WaitGroup на каналах? Как?


https://play.golang.org/p/978PvDYjLbb

9. Что ты использовал из пакета sync(кроме Mutex и WaitGroup)?


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

10. Что выведет код


func main() {
v := 5
p := &v
println(*p)

changePointer(p)
println(*p)
}

func changePointer(p *int) {


v := 3
p = &v
}

5
5
Почему? Как нужно изменить функцию changePointer, чтобы вывело 5 и 3 (в оригинальной версии
выводится 5 и 5)?
https://play.golang.org/p/p01jCK9-lkc

11. За сколько примерно выполнится приложение — за 3 секунды или за 6?


func worker() chan int {
ch := make(chan int)

go func() {
time.Sleep(3 * time.Second)
ch <- 42
}()

return ch
}

func main() {
timeStart := time.Now()

_, _ = <-worker(), <-worker()

println(int(time.Since(timeStart).Seconds())) // что выведет - 3 или 6?


}
6
Что нужно изменить, чтобы код работал за 3 секунды?
Как вариант, не читать из канала, возвращаемого функцией worker(), тогда горутина, пишущая в этот канал,
его не заблокирует