Хочешь уверенно проходить IT-интервью?
Мы понимаем, как сложно подготовиться: стресс, алгоритмы, вопросы, от которых голова идёт кругом. Но с AI тренажёром всё гораздо проще.
💡 Почему Т1 тренажёр — это мастхэв?
- Получишь настоящую обратную связь: где затык, что подтянуть и как стать лучше
- Научишься не только решать задачи, но и объяснять своё решение так, чтобы интервьюер сказал: "Вау!".
- Освоишь все этапы собеседования, от вопросов по алгоритмам до диалога о твоих целях.
Зачем листать миллион туториалов? Просто зайди в Т1 тренажёр, потренируйся и уверенно удиви интервьюеров. Мы не обещаем лёгкой прогулки, но обещаем, что будешь готов!
Реклама. ООО «Смарт Гико», ИНН 7743264341. Erid 2VtzqwP8vqy
1. Slice (слайс)
Slice – структура данных, которая похожа на массив, но с возможностью изменения количества элементов. Слайс содержит ссылку на начало области данных: длину (количество элементов заданного типа) и емкость (capacity). Последнее представляет собой количество элементов в области памяти с первого элемента слайса и до конца этой области. Например, если в памяти 25 элементов и начало слайса указывает на 5-й элемент, то емкость будет – 20 (длина при этом может быть любой от 0 до 20, если больше, то произойдет выделение большего количества памяти и копирование имеющихся значений из старой области в эту новую, а также добавление новых элементов).
Поведение slice представлено в таблице:
2. Map
Map – структура данных, реализующая hash map. Hash Map позволяет по ключу получить значение за время O(1). На запись по ключу значения элемента также тратится O(1) времени.
Чтение элемента в Golang может осуществляться с помощью конструкции:
Здесь ok
возвращает true
в случае, если элемент существует и прочитан и false
, если нет. Если элемента нет, то всегда возвращается нулевое значение данного типа в качестве значения.
Поведение map
представлено в таблице:
состояние | действие | результат | пример |
элемент есть | чтение | значение элемента, ok: true | https://go.dev/play/p/3-KR5o2s_PP |
элемент есть | запись | перезапишет существующее значение | https://go.dev/play/p/Z2K9FuJd15e |
элемента нет | чтение | значение: нулевое для данного типа, ok: false | https://go.dev/play/p/gHy8zKFc8JK |
элемента нет | запись | запишет новое значение по данному ключу | https://go.dev/play/p/Y487vvnOD-y |
nil | чтение | значение: нулевое для данного типа, ok: false | https://go.dev/play/p/9ysg-MjuhXr |
nil | запись | паника | https://go.dev/play/p/VrXlQK1XaLd |
nil | len | 0 | https://go.dev/play/p/BJ3_cRC8ZSL |
nil | cap | ошибка компиляции | https://go.dev/play/p/siDXBNoNl5T |
nil | сравнение с nil | true | https://go.dev/play/p/zJDrAbVumih |
инициализирована | len | количество значений в мапе | https://go.dev/play/p/BQ-yb71aSaQ |
инициализирована | cap | ошибка: invalid argument for cap | https://go.dev/play/p/oLQKWp_hHxW |
инициализирована | сравнение с nil | false | https://go.dev/play/p/zTMnkuE2qEP |
3. Channel
Channel – структура данных, которая используется для взаимодействия между горутинами. Горутина может послать сообщение (значение определенного типа данных) в канал, другая горутина может прочитать сообщение из канала. Каналы могут иметь или не иметь внутренний буфер.
В первом случае при записи в канал значения добавляются во внутренний буфер, а чтение тоже производится из него. Если буфер заполнен, писатель блокируется до того момента, пока не освободится место. Если буфер пустой, то блокируется читатель при попытке чтения до тех пор, пока в буфер не поступит информация.
В случае если буфера нет, писатель блокируется, пока читатель не будет готов прочесть, аналогично блокируется читатель, пока писатель не запишет информацию.
Оператор select
позволяет читать из нескольких каналов. В каком канале появится первое сообщение, тот и будет прочитан и продолжится исполнение читателя.
Канал может иметь состояние «открыт» (тогда он работает как обычно – можно читать и писать) и «закрыт» (предполагается, что канал более не нужен и записывать больше ничего нельзя в такой канал).
Поведение небуферизованного канала:
состояние | действие | результат | пример |
открыт | чтение (receive) | если писатель готов, то чтение или ожидание информации в канале | https://go.dev/play/p/-kZO7U3pEPY |
открыт | запись (send) | если читатель готов, то запись или ожидание, пока не будет готов | https://go.dev/play/p/gOJ8PP5ID6C |
открыт | select | чтение из первого канала, где есть информация либо переход в default ветку (если объявлена) | https://go.dev/play/p/qsQJixb1J4l |
закрыт | чтение (receive) | чтение нулевого значения заданного типа (без ожидания) | https://go.dev/play/p/mZ-a-uau1qP |
закрыт | запись (send) | паника | https://go.dev/play/p/i1M9adPQIiP |
закрыт | select | чтение нулевого значения заданного типа (без ожидания) | https://go.dev/play/p/TG-PwYPh3e_h |
nil | чтение (receive) | читатель блокируется навсегда | https://go.dev/play/p/_iXBO6_C3oC |
nil | запись (send) | писатель блокируется навсегда | https://go.dev/play/p/_iXBO6_C3oC |
nil | select | пропускает канал | https://go.dev/play/p/p5SfXeSezWW |
Поведение буферизованного канала практически аналогичное, но с учетом наличия внутреннего буфера. В случае закрытия канала туда нельзя будет более записывать значения, но при чтении будут сначала прочитаны все, которые имеются в буфере, а после этого поведение будет как у небуферизированного – будут возвращаться нулевые значения соответствующего типа:
открыт | чтение (receive) | если есть информация в буфере, то чтение или ожидание появления информации | https://go.dev/play/p/5vq_JEUH1de |
открыт | запись (send) | если в буфере есть пустое место – запись, если нет – ожидание, пока не появится | https://go.dev/play/p/CcQM-CQe2WE |
открыт | select | чтение из первого канала, в буфере которого есть информация либо переход в default ветку (если объявлена) | https://go.dev/play/p/p6BfZmwEmdd |
закрыт | чтение (receive) | чтение всех значений из буфера, а после – чтение нулевого значения заданного типа (без ожидания) | https://go.dev/play/p/3RFfAvLpWe2 |
закрыт | запись (send) | паника | https://go.dev/play/p/XTL48XHMwNp |
закрыт | select | чтение всех значений из буфера, а после – чтение нулевого значения заданного типа (без ожидания) | https://go.dev/play/p/yVqQ-DnWd2B |
nil | чтение (receive) | читатель блокируется навсегда | https://go.dev/play/p/P6NzkZvgdAk |
nil | запись (send) | писатель блокируется навсегда | https://go.dev/play/p/P6NzkZvgdAk |
nil | select | пропускает канал | https://go.dev/play/p/N2G72DkTPFY |
Пожалуй, это все, что я хотел рассказать. Надеюсь, что эта небольшая заметка поможет кому-то и, возможно, окажется полезной как напоминание, так как иногда, не работая долго с той или иной структурой данных, можно забыть особенности ее поведения.
У вас остались какие-нибудь вопросы?