Mock - собеседование от старшего разработчика из Ozon (секция Go)

Подготовка к собеседованию на Golang Developer

Транскрипция видео:

  • так Ну давай тогда м-м начнём каких-то таких теоретических аспектов э ну такой часто задаваемый вопрос всегда любят его спрашивать Чем отличается слайс от массива массив это у нас статического размера контейнер Вот это и вроде как совершенно точно контейнер динамического массива Однако он может ссылаться на какой-то уже существующей массив можно взять собственно какую-то средство как длина емкость В общем Когда у нас слайс выделяется ему задается какая-то емкость память выделяется под данное количество

    00:00:00 - 00:01:39

  • элементов но они не заняты длина Это количество фактически занятости человек получается когда у нас доходит длина иначе количество элементов которые хранятся в этом слайсе до capacity необходимо нам расширить память под него выделяется память обычно это в два раза уделяется больше размер памяти текущие элементы туда переставляются то есть копируются копируется эти элементы далее возвращается если уже говорить функция возвращается указатель на новый слайс соответственно здесь которые надо не попасть когда мы Передаем слайс

    00:01:10 - 00:02:51

  • аргументам нужно понимать будем добавлять то не нужно ожидать из вызывающих Окей Ну так чтобы зафиксировать про слайсы Какая симпатическая сложность получения элемента и слайса берем смещение от начала массива адрес совсем несколько смотреть и берем оттуда элемент вот у нас есть продолжим другую тему теперь есть объектно-ориентированные языки которые там реализуют эти всем известные проводник типа там капсуляции полиморфизмы наследования оно как-то иначе Вот можно сказать как выглядят эти три аспекта

    00:02:06 - 00:03:33

  • Ну у нас нету наследования в гоу У нас есть просто структуры мы Если хотим как-то расширить функционал какой-то то мы можем просто Настя структуру в нее называется в классическом опенинг такого понятия Это значит что все там члены и функции какой-то структуру которую мы вставляем внутрь Да она содержится в новой её охватывающая структуре Ну соответственно можем использовать её без дополнительных там операторов разрешение контекста сразу привык будто бы они внутри вот внешней структуре и участвовали Ну и также нас полиморфное

    00:03:06 - 00:04:33

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

    00:03:50 - 00:05:08

  • компиляции со скоростью количество связей меньше поэтому я предполагаю Можно ускориться компиляцию опять предположение может оно не так Может просто для того чтобы связаться компонентов соответственно тоже можем инкапсулировать какие-то которые внутри нас делать членами Вот и статический полиморфизм появился абстракции такого нету то есть мы не прячем имплементацию за этот самый интерфейс такого нету Вроде вот так вот этот момент что значит мы не прячем в статусы за интерфейсом Да я просто там где публичный приватная

    00:04:30 - 00:06:03

  • часть класса здесь такой есть конечно да там можно выставить наружу но здесь не получится например дать хедер клиенту и скомпилированную сошку например чтобы он использовал наверное еще один такой теоретический вопрос который важен в голову является вот эти Гуру Тины что это такое чем они там отличаются от потоков это собственно концепция она не новая как таковая были концепции То есть раньше это был он как был раньше потом вернусь в общем концепция такова что у нас переключение трендов операционных систем Это довольно

    00:05:30 - 00:07:11

  • дорогая операция за счет того что нам нужно контекст одного потока операционной системы сохранять в память куда-то да и собственно загружать для другого который вытеснил текущий это при определенных нагрузках это уже начинает роялить Например если у нас какие-то эти самые операции то много потоков они будут мешаться А собственно сама концепция того чтобы параллельный параллельно писать это удобно Для этого сделали легкие потоки по факту это не является у нас новым потоком операционной системы Это просто

    00:06:42 - 00:08:09

  • какая-то сущность является которая внутри соответствующего потока на то вытесняется там другая берется то еще какая-то то есть ну грубо говоря мы получаем фишки немного по точности легкие без минусов как таковых связанных с переключением самых потоков операционной системы безусловно есть их несколько штук работает этой программе то есть там по количеству обычно берется логических логических ядер то есть вот удар равняется например вот 8 потоков создается каждый из них работает своей очереди есть там в общем-то эти

    00:07:25 - 00:08:48

  • буратинками червяк стоят он берёт одну не исполняет потом переключается другую то есть после 1.14 она стала примитивными многозадачность примитивные многозначность это когда у нас в какой-то момент времени может совершенно непредсказуемый для нас как для программистов прозрачность Может просто взять и выяснится а-а с потока исполнения какая-то гарутина заместиться другой а то 1,14 лет 13 лет версии там был Кооперативный у нас то есть были какие-то точки в которых отдавался этот самый добровольный

    00:08:09 - 00:09:25

  • отдавался контекст исполнения На какие проблемы с этим были связаны Почему вообще переделали Ну если опять же у вас какая-то грудью рутину какую-то ципулу на задачу выполняет очень много считает там внутри нет прерывания например то тогда остальных будут голодать на этом потоке в частности вот так вот это не очень честно распределение получается было Вот они А кстати здесь Довольно интересно это сделано думал если взять потоки операционной системы там принципе понятно да как переключение происходит то есть

    00:08:46 - 00:10:09

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

    00:09:33 - 00:11:03

  • конкретному потоку потоку операционной системы используется Сибирь чемпиона нас получает у него рабочих срабатывает и он собственно выбирает другую рутину для того чтобы А ну и соответственно когда они в какую-то операцию уходят они тоже они отдают или Могут ли отдавать или точно дают наверняка не скажу контекст исполнения для другой рукены если там будете делать вызовы какие-нибудь то точно там даже специально этот есть так скажем компоненту В этой системе который для сетевых вызовов на кулер Называется какой-то он типа уводит их в

    00:10:18 - 00:11:48

  • сторону Ну я вам так скажу что есть Класс вот этих вот вызовов Input они все менеджеры какой-то пул должны вставать собственно потом раскидывает и собственно я боюсь а встречала где-то это было прогуливание про го что они все [музыка] операции они выполняются на самом деле отдельным потоком операционной системы в стороне стоят в отдельном потоке это поэтому есть важная оговорка что потоков операционной системы на самом деле может быть больше чем это легко да у вас ноутбуки в любой момент времени

    00:11:03 - 00:12:35

  • крутится гораздо больше потоков операционной системы нежели есть логических ядер Это для любой программы пишут типа ну вот запустили у нас там го Макс Фокс 8 Значит только 8 этих потоков бывает немножко заговорился если говорить разница опять между рутинных между грузинах и по такому операционной системы то у нас за счет груди Мы тоже память экономим в том плане что у нас стек стэк на потоке операционной системы 8Gb сейчас на 32 на 32 [музыка] битных системах было 4 мегабайта памяти то здесь на грудину по дефолту выдается 4

    00:11:56 - 00:13:40

  • килобайта в том что они очень просто грузится он растет довольно легко операционной системы мы Кроме Main treta мы не можем увеличить себя стык размер стека Вот Но мы его можем задать на стадии отдавать красную зону которая бы нам канарейка работала переполнение случилось или нет по дефолту происходило нет опции по дефолту выставлены но там справедливости ради я собирал софт силангом А здесь просто плюсом было это в бытность еще мою работу плюсовиком вот и кстати важно что еще могу отметить прогутины

    00:13:01 - 00:14:38

  • если мы пишем какую-то сервис который создает много воркеров этих то возможно имеет смысл задуматься О том чтобы сделать пол этих воркеров потому как если каждый в какой-то момент своей жизни будет запрашивать еще морстэк да будет то соответственно Он каждый раз будет выделяться если мы этот worker будем переиспользовать то у нас собственно такой вот стек максимум запросил буратину прошлый раз он будет оставаться и за счет этого мы сэкономить можем это я кстати такой лайфхак прочитал в статье тубера м3 м3

    00:14:09 - 00:15:42

  • делали вот они собственно падение были связаны с этим они экипажили как бы вот собственно раскрутили довольно прикольно в стандартном пакете синк пуллер разные вещи здесь просто если динамическую память А про динамическую память можно тоже отдельно поговорить или Довольно интересно Там очень много чего есть [музыка] сингл про который вы упомянули сейчас ну это да например Когда нужно много выделять память большое количество объектов одинакового размера тогда мы можем использовать это место и режет на вот эти кусочки

    00:14:55 - 00:16:31

  • когда мы его там запрашиваем просто из готового выделяет Ну во-первых это становится быстрее чем я сейчас объясню почему это становится быстрее чем запрашивание молоком условно молоком Да памяти из кучи И это еще нам экономить память почему так происходит потому что потому что когда мы запрашиваем динамическую память при помощи молока мы идем в некуда мы идем идем в Липецке в стандартно библиотеку на В общем она держит У себя структуры вспомогательные то есть таким образом чтобы Какова ты не можешь запросить у

    00:15:53 - 00:17:27

  • операционной системы там какое-то количество байт памяти можно запросить только страницу собственно абстрагируют таких проблем нас абстрагируют это стандартная библиотека которая Практически везде используется получается что она сама просит страницы памяти у операционной системы нарезают необходимым количеством на на необходимые кусочки то есть и содержит несколько связанных списков у себя она содержит несколько связанных списков которые подходят под определенный типоразмеров То есть если мы маленькие

    00:16:44 - 00:17:48

  • выделяем там например 20 байт нам нужно у вас вот лет 10 назад я смотрел когда молоко там там для маленьких объектов он сразу выделял из отдельного Пула примерно 80 байт то есть его сразу переход 4 раза это 80 байт пока он не закончится потом конечно новую страницу будет нарезать Но помимо этого Когда вы получаете указатель вот молока он указывает Вы можете начинать писать но этого участка памяти стоят два указателя которые указывают самой кучи на место вот этого чат Откуда он был выделен то есть это следующий

    00:17:19 - 00:18:34

  • предыдущий элемент связанный список То есть получается у нас по памяти который показатели то есть по 8 байт на современных md64 архитектурах Таким образом получается что люди пишут кастомные локации уступал недавно про как раз рассказывал как он там написал локатор кастомный угол Но он типа из песок пришел Такой типа Сейчас я вам тут наделаю делал Ну мне не попадались задачи когда мне необходимость возникла в написании [музыка] локатор кастомного но у нас на одном проекте боролись на плюсах написали корутины

    00:17:58 - 00:19:24

  • говорят об этом я честно не программирую 15 год 14 лет решит Нет не было почти впусте там как эти корутины писались то есть мы что-то аналогичное вот этим буратином писали и был диспатчер свой диспанчер который в общем-то у меня просишь создать [музыка] и в общем-то переключение это было через контекст вызов по моему России вот мы пытались использовать контекст постов но он давал ошибки на этих самых намаках Вот он я не помню мы это делали сами вот просто все регистры сохраняли [музыка] Интересно как мы далеко ушли с этими

    00:18:55 - 00:21:05

  • разговорами про этот нормально Давай тогда перейдем немного коду посмотрим пару задачек которые любят тоже давать некоторые так вот подсветку включу банальный вопрос типа что выведет программа Сейчас посмотрим мы вызываем функцию А который Так мы подъедут значит этот самый мы выделяем этот дефолтный слайс добавляем wix 0 добавляем X добавляем единицу добавляем двойку это все у нас может идти спокойно через реологии а потом сюда же в этот X мы добавляем тройку и возвращаем опять же указательные игреки а кручное

    00:20:41 - 00:22:25

  • будет содержаться в Z А в игреки здесь Мне сложно сказать Вот так Вот потому что они нужно понимать Было ли выделение релокация когда мы добавляли четверку или нет но что-то мне подсказывает что было потому что по степеням двойки растут размеры да то есть у нас три тоже четыре элемента получается то есть я рискну предположить что Y у нас 01234 на самом деле нет давай подумаем еще Ну типа сделать можно просто расписать Подожди подожди Сейчас я мог быть невнимательным потому что мы же в X добавляем 0 1 2

    00:21:38 - 00:23:09

  • и мы такие добавили kicksu тройку И вот она стала в Y а потом мы кексу добавили четверку То есть это 0123 и 0124 наверное вот так Давай попробуем куда там все сохраняется не скажу какие хорошо дальше у нас Мы добавляем туда то есть у нас Копатель увеличится до двойки если я не ошибаюсь а сам массив я здесь а здесь что у нас Мы добавим единичку То есть у нас Слен увеличится до нас такая в первом случае теперь у нас Что значит у нас мы достигли Копатель при добавлении 6 строки у нас идет пометить себе что указатель изменился

    00:22:28 - 00:24:08

  • получается а здесь у нас он такой же целевое у нас нулевой попасть значит X1 небольшой ролик потом здесь у нас Мы добавили уже после этого мы вернули их второе вот потом на что Лена У нас тройка стал а здесь у нас уже четверка потому что мы на предыдущем этапе выделили он также у нас у тебя было попасть Один он делает два на 6 строке он выделяет новый кусок получается памяти чтобы уместить два элемента ему опять придется потому что здесь одинаковые мы вернули X1 или я здесь ошибаюсь X1 должен вернуть

    00:24:21 - 00:26:16

  • так нет смотри у нас же потом при добавлении когда мы x 3 добавляется мой строки вот здесь вот здесь вот уже уже он другой то есть при вставки он поймет что нас рынок почти одинаковые короче возьмет увеличен два раза и после пятой строчки одинаковые Ему же тоже нужно на 6 строчке здесь получается уже на седьмой строке уже он получается здесь у нас что у нас Мы добавляем [музыка] У нас 4 получается и C4 мы здесь еще ничего не выделяем а получается Y у нас Да с этим То есть у нас но мы используем здесь опять же X

    00:26:09 - 00:28:02

  • который был седьмой строки вот с этой а он не изменился он такой же остался а он не изменился он остался такой же то есть мы как встретим добавляем четверку то есть мы должны перевыделить его то есть уже 8 до Сейчас я напишу здесь уже у нас Z будет равняться не так давай вспомним как слать под капотом указатель на выделенную память плюс длину и плюс К пасите структура из трех элементов смотри у нас по сути X вот этот структура из трех элементов вот этот Обозначил это именно указатели то есть вот вы Y и у x у него

    00:27:40 - 00:29:17

  • совпадает указатели на базовый массив но структуры разные правильно то есть разное значение ln и capassi Ну могут быть [музыка] Значит у нас здесь Так это что у нас значит здесь 34 так здесь добавляем у нас была такая X3 указатель на память потом [музыка] длина увеличили это все также осталось когда мы в девятой строке добавляем что у нас получается мы копируем то что у нас было в y3 указывало на новые y3 это мы все копируем и просыпаемся больше выделяем этот самый указательную 9 строчке Мы работаем вот с этой структурой у которой

    00:28:44 - 00:30:47

  • lm3 я понял ошибку свою да то есть там не просто показатель Передаем здесь 012 012 значит 4 было добавляем [музыка] [музыка] [смех] на какую память они указывает Y и одинаковую память здесь Y Подожди они на одну и ту же память должно указывать да на память они одну и ту же указывает не было перевыделения передается что ли Ничего себе это такой наркоманский пример который Ну типа проверяет размышление об этом насколько [музыка] хорошо себя представляю как тройка да да почему-то зациклился на этих самых

    00:30:04 - 00:32:13

  • на указателях на память не подумал что возвращается [музыка] Ну там тоже типа пример что выведет программа так Так у нас есть структура с именем просим поменять имя женщины по указателю Передаем сюда возвращаем новую структуру там возвращаем новую структуру при помощи копирования туда с именем Элис значит здесь у нас значит [музыка] сам указатель Разумеется мы откопировали здесь сам указатель от копировали ссылается на тот же регион памяти что и песен один хорошо и при помощи разменования мы копируем в эту область памяти

    00:31:59 - 00:33:52

  • структуру нас новыми минимализ Вот и я рискну предположить что здесь 1 будет Боб выведена здесь или после изменения А теперь Объясните действительно скопируется значение не скопируется показателю понятно Вот дальше Вот это хрена конструкция она просто локальная указатель его подменит ну то есть значение на которое показатель указывает подменено на Элис но действовать это будет в рамках локальной перемены которые она не будет влияние иметь на указатель который указывает вот здесь не понял что такие рассуждения не очень корректно

    00:33:45 - 00:35:32

  • как я сказал здесь почему-то не сейчас я попробую переформулировать Так мы скопировали указатель потом мы пытаемся разменовать Ну то есть чем мы делаем разменование мы пытаемся Достучаться до того куска памяти на который он ссылается значение этого куска это Бомб будет потому что он указывал на бомбу вот и он как бы разминовывая если мы присылаем значение то он поменяет в указатели туда куда он указывает скажем так а что изменилось с первым примером Да с первым примером Ты был прав А вот здесь нет выводит

    00:34:59 - 00:36:34

  • буквы [музыка] Я короче скопировал уже ну я типа даю когда задачу неисправленный пример посмотрим здесь конечно Да здесь-то конечно вот этот самый такой ты копии указателя присваиваешь другое значение тот прообразный указателя не меняется здесь то понятно Да что-то как-то я исправлю себя в этих заметках я могу выкрутить сказать я проверял тебя так надо что сделать Ну понять сейчас работает ли 68 69 строки У нас есть структура фу пустая есть два метода на эту структуру который должен говорить что структуру

    00:36:54 - 00:38:14

  • должны примитировать B и C дальше int Мы создали зачем-то потом а Короче мы такие говорим здесь хотим получить как интерфейс собой мы говорим вот он Да Окей сказали мне потом этот кастуем его 68 По моим ощущениям Она не должна сработать насколько я представляю потому что мы уже когда кастовали так интерфейсу б Вот в этой функции мы должны были потерять информацию о том какой была структура исходная но там интерфейсах есть указатель на объекты на и на Тип и на Тип который был исходный Вот чем дело

    00:38:44 - 00:40:31

  • Думаю здесь вот этого момента в большинстве языков тебе могу сказать что это не про канала врасти бы не про каналов плюсах бы не проканала Какие ставки на гол вот вопрос интересный Меня смущает что то что там интерфейс они Да они там подводят они имеют указатель на исходно исходный объект и на тип его да вопрос Будет ли Вот это преобразование работать туда выше вот в чём дело посмотрю хорошо если он у нас сработал этот вызов не должен сработать есть два варианта восьмая строка либо сработает либо Не

    00:39:50 - 00:41:27

  • сработает если она срабатывает то 69 не должна сработать потому что мы вызываем метод объекта который не умеет этого делать интерфейсы это первом варианте развития А если Не сработает здесь это преобразование 689 они Должны сработать собственно что упирается всё будет ли он отдать пытаться подниматься кассе или нет А мне кажется что нет нет было бы вот поэтому я наверное склоняюсь ко второму варианту что-нибудь другое Не сработает сохраняется информация динамическом значении динамическом типе поэтому Благодаря этой Он позволяет

    00:41:01 - 00:42:31

  • [музыка] по указателю который на исходной идет он пытается исходный объект получается преобразовать большинство языков не содержат информацию о исходном объекте вот я может быть не знаю предположение выскажу что других языках просто других всяких этих конструкций полно которые добавляют какого какой-то но если говорить о трейдах Прости например периодически приходится сами писать здесь если говорить то там нет Если ты внутри информации никакой не будет всё собственно привёл кроме интерфейсов толком больше ничего

    00:41:54 - 00:43:20

  • нет и поэтому может их и так и сделать чтобы они какой-то гибкости и больше достигали Ну то есть смотри первый вариант мой до конца был верным или нет то есть шестьдесят девятый это сработает или нет Если нет конечно а кстати вот что такое интерфейс Зачем пустая структура либо как маркер может служить либо как интерфейс который матчатся в любой тип То есть если [музыка] мы хотим передать что угодно функции то мы пустой интерфейс Передаем и там и там уже мы сёршнами или чем-то разбираемся если там говорить его как о маркерах то

    00:42:47 - 00:44:16

  • где-то мне попадалось боюсь ошибиться опять же что если мапов у которых в качестве значения пустой интерфейс то там как сайт работает но это за счет того что ей не нужно память под объект значения [музыка] Да да там оптимизации какие-то были просто с этим связано помню поэтому говорю примерчик вот такой вот Да сколько же примеров то еще будет смотреть Так что у нас здесь это очень распространенный пример [музыка] будет захватывать [музыка] другие варианты Вот именно в таком виде вот Ну вот запустилась функция в грудине

    00:43:54 - 00:45:39

  • Да на 83 когда она запустится вот прям сейчас или нет нет она будет запуститься когда мы сворачиваться перед выходом она не на выходе цикла будет А если раз перепутал ой да Она запустится Слушай я запустится когда решит планировщика все такое Но типа Какие проблемы могут с этим связаны в конкретном коде в конкретном коде Ну например может остаться Так что функция Main завершится когда еще до того как завершатся все 10 грудин например А если касательно того что будет у нас здесь давай подумаем у нас начинает

    00:45:26 - 00:47:06

  • выполняться первая операция цикла у нас и равно единички мы такие Ага нам нужно запустить эту самую рутину Давай короче создаем глазуру здесь контекст мы копируем контекст скопируется и этот самый нолик от копировался туда окей давай дальше она значит пошла это функция гарантина в очередь стала там давно исполнение когда до неё Это беспочёрки доведётся и так 10 раз получается мы наплодили 10 гарантин передали Вот это самое туда замкнули значение этого счетчика и и что у нас В итоге получилось Мы не знаем когда они

    00:46:27 - 00:47:57

  • начнут выполняться ближайшее время то скорее всего не сразу и выполнить Ну то есть в целом обычно считается корректным ответ но этот вопрос Но первоначально что типа это может что-то успеть может что-то не успеть хз если коротко будет как бы нам так сделать чтобы точно все выполнялись а почему Дан делаем не внутригрутины ой недавно этот потому что этот самый может опять сама ситуация которую я объяснил может случиться То есть если я правильно просто Почему я вот так вот сделал Ну потому что ровно по той же причине

    00:47:14 - 00:48:40

  • которую я вот рассказывал до этого ты смогут не всем отработать то есть мы должны знать наперед сколько грудин будет чтобы стать какие-то могут не доработать Да это да По поводу этого любят Обычно вот так вот делать Ну понятно с принтом это не сильно актуально Но если там какая-то логика дофига навалено Да нормально Просто у тебя несколько этих же может быть точек выхода из функций просто чтобы не этот самый не ошибиться даже если знаешь почему [музыка] все 10 значений в произвольном порядке [музыка]

    00:48:49 - 00:50:12

  • а там же очередь Айка хитроу очереди в смысле я с порядком именно со значениями что-то не так вот тут нюансы есть вот замыкание просто смотри если внутри тела цикла А мы создаем же замыкание и мы туда текущий контекст замыкаем вот там что-то с этим с указателем он будет в общем-то Вот и на 88 именно причем Это только в циклах по моему да такая штука если девяток выйдет опять знаешь это корректный ответ антифайн бихеви потому что Ну кстати на самом деле больше всего не девяток выводится десяток Ну потому что

    00:50:18 - 00:51:58

  • уже не попадают девятки можно сказать

    00:51:45 - 00:51:56