Библиотека Go для собеса | вопросы с собеседований
6.87K subscribers
218 photos
6 videos
1 file
415 links
Вопросы с собеседований по Go и ответы на них.

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

Учиться у нас: https://proglib.io/w/0b524a15

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
💬 Зачем для подсчета времени в Go использовать тип данных int32, если он содержит отрицательные значения?

Отрицательными целыми числами представляется время до эпохи UNIX, а положительными — после неё. Таким образом, значение счетчика -100 означает момент времени за 100 секунд до полуночи 1 января 1970 года, а +100 секунд указывает на 100 секунд после этой даты.
👍21
👩‍💻 Range Over Function Types в Go 1.23

Текстовая версия выступления Ian Lance Taylor на GopherCon 2024 о том, почему эта фича была добавлена, что из себя представляет и как ее использовать.

👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
💬 Что из себя представляет проблема false sharing?

Если у двух строк кэша общие адреса, процессор помечает их как общие (shared). Если один поток изменяет общую строку, он помечает обе как измененные (modified).

Чтобы гарантировать когерентность кэшей, требуется координация между ядрами, что может значительно снизить производительность приложения. Эта проблема называется false sharing (ложный обмен информацией).
👍4
💡Кстати, стандартная библиотека Go включает в себя простой в использовании обратный прокси-сервер

httputil.NewSingleHostReverseProxy создает обратный прокси-сервер, который перезаписывает URL-адреса на указанный целевой хост.

👉 Документация
👍6
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.

Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.

Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.

👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
💬 В чем суть модели PMG в Go?

PMG расшифровывается как P (логические процессоры), M (машинные потоки) и G (горутины). Основная идея заключается в том, что каждый логический процессор (P) может одновременно работать только с одним машинным потоком (M). А чтобы горутина (G) могла выполняться, она должна быть привязана к потоку (M).

Это сводится к двум ключевым моментам:

1. Если у нас есть n логических процессоров (P), мы можем параллельно запускать до n горутин, при условии, что у нас доступно как минимум n машинных потоков (M).
2. В любой момент времени только одна горутина (G) может выполняться на одном процессоре (P). Таким образом, когда P1 занят выполнением G, никакая другая G не может выполняться на этом P1, пока текущая G не будет заблокирована, не завершит выполнение или не произойдет что-то, что освободит этот процессор.
🔥18👍4
💬 Почему GOPATH режим был заменён Go модулями?

Основная причина заключается в том, что режим GOPATH не включает в себя понятие версий пакетов.

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

В отличие от этого, Go модули управляют зависимостями с использованием конкретных версий, что гарантирует, что все используют один и тот же код. Когда мы клонируем проект и загружаем его зависимости, Go модули проверяют эти зависимости с go.sum файлом, чтобы убедиться, что они такие же, как использовались изначально.
👍26
💬 Может ли адрес значения измениться во время выполнения Go-программы?

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

Например, следующий код выведет два разных адреса:
package main

//go:noinline
func f(i int) byte {
var a [1 << 12]byte
return a[i]
}

func main() {
var x int
println(&x)
f(100) // увеличиваем стек
println(&x)
}
👍17
👾 -35% на хардкорный курс по вышмату

На курсе вы получите все необходимые знания для старта карьеры в DS или аналитике – https://proglib.io/w/568af10b

19 490 рублей 29 990 рублей

Что еще вас ждет на курсе:

▪️ Полугодовая программа от преподавателей ВМК МГУ;

▪️ 150 практических заданий и 47 видеолекций;

▪️ Бессрочный доступ ко всем материалам курса;

▪️ Развернутая обратная связь по всем домашним заданиям, а также ссылки на полезные дополнительные материалы.

🌚 Переходите на сайт, читайте подробности и заходите на обучение по самым выгодным условиям – https://proglib.io/w/568af10b
Please open Telegram to view this post
VIEW IN TELEGRAM
1
💬 Когда мы передаем срез в unsafe.SliceData, какие проверки он выполняет, чтобы выяснить, что возвращать?

🔻 Если capacity среза больше 0, функция возвращает указатель на первый элемент среза (array[1]).
🔻 Если срез равен нулю, функция просто возвращает ноль.
🔻 Если срез не равен нулю, но имеет нулевую capacity (пустой срез), функция возвращает указатель, но он указывает на «неопределенный адрес памяти».

👉 Подробнее
👍3
💬 Каким образом Go создает новый массив для адаптации растущего среза?

Go обычно удваивает емкость растущего среза, но это меняется, как только срез достигает определенного размера. Если срез небольшой, удвоение емкости обеспечивает быстрый рост. Но бесконечное удвоение емкости приведет к огромным выделениям памяти по мере увеличения среза. Чтобы избежать этого, Go корректирует темпы роста, как только срез достигает определенного размера, обычно около 256. В этот момент рост замедляется по следующей формуле:

oldCap + (oldCap + 3*256) / 4
👍23🔥1
Forwarded from Библиотека программиста | программирование, кодинг, разработка
🏗️ Структуры данных для разработчиков: 10 самых важных

Структуры данных — фундамент эффективной разработки. Кратко разберем 10 ключевых структур данных, которые необходимо освоить каждому разработчику для создания производительных и масштабируемых приложений, а подробнее читайте в статье👇

🔹 Списки отлично подходят для хранения и обработки упорядоченных данных и полезны в различных приложениях, таких как управление задачами, ленты соцсетей и корзины интернет-магазинов.
🔹 Массивы — упорядоченная коллекция элементов фиксированного размера и хорошо подходят для ситуаций, где размер коллекции известен или редко меняется.
🔹 Стеки следуют принципу «последним пришел — первым вышел». Они идеальны для реализации операций отмены/повтора в текстовых редакторах или ведения истории просмотров в веб-браузерах.
🔹 Очереди работают по принципу «первым пришел — первым вышел». Они подходят для управления заданиями печати, отправки действий пользователя в играх на сервер или обработки сообщений в чат-приложениях.
🔹 Кучи используются для планирования задач и управления памятью. Они особенно полезны в реализации очередей с приоритетами, где нужен доступ к элементу с наивысшим или наименьшим приоритетом.
🔹 Деревья организуют данные иерархически. Они полезны для представления данных с естественными иерархиями или связями и могут использоваться в различных приложениях, таких как индексация баз данных.
🔹 Хеш-таблицы позволяют эффективно искать, вставлять и удалять данные. Они используют хеш-функцию для сопоставления ключей с соответствующими местами хранения и обеспечивают доступ к сохраненным значениям за постоянное время.
🔹 Суффиксные деревья специализируются на поиске строк в документах, что делает их идеальными для текстовых редакторов и алгоритмов поиска.
🔹 Графы отслеживают отношения и находят пути, что делает их незаменимыми в социальных сетях, рекомендательных системах и алгоритмах поиска путей.
🔹 KD-деревья хороши для поиска ближайших соседей и важны для картографических приложений и геолокационных сервисов.
👍6
🏃 Самоучитель по Go для начинающих. Часть 16. Тестирование кода и его виды. Table-driven подход. Параллельные тесты

В статье познакомимся с концепцией тестирования кода и её основными видами, изучим инструменты стандартного пакета testing, научимся запускать и визуализировать тесты. В качестве практического задания напишем и протестируем алгоритм «Решето Эратосфена».

👉 Читать гайд

📌 Остальные части в серии:

1. Особенности и сфера применения Go, установка, настройка
2. Ресурсы для изучения Go с нуля
3. Организация кода. Пакеты, импорты, модули. Ввод-вывод текста.
4. Переменные. Типы данных и их преобразования. Основные операторы
5. Условные конструкции if-else и switch-case. Цикл for. Вложенные и бесконечные циклы
6. Функции и аргументы. Области видимости. Рекурсия. Defer
7. Массивы и слайсы. Append и сopy. Пакет slices
8. Строки, руны, байты. Пакет strings. Хеш-таблица (map)
9. Структуры и методы. Интерфейсы. Указатели. Основы ООП
10. Введение в ООП. Наследование, абстракция, полиморфизм, инкапсуляция
11. Обработка ошибок. Паника. Восстановление. Логирование
12. Обобщенное программирование. Дженерики
13. Работа с датой и временем. Пакет time
14. Интерфейсы ввода-вывода. Буферизация. Работа с файлами. Пакеты io, bufio, os
15. Конкурентность. Горутины. Каналы
🔥41
💬 Срезы в Go всегда аллоцируются в куче?

Срезы состоят из двух частей: заголовка среза (который представляет собой структуру с тремя полями) и базового массива, который может находиться либо на стеке, либо в куче.

1. Первый случай: и срез, и базовый массив находятся на стеке.

func doSomething() {
a := byte(1)
println("a's address:", &a)

s := make([]byte, 1)
println("slice's address:", &s)
println("underlying array's address:", s)
}


Вывод примера показывает, что и переменная a, и срез s, и его базовый массив выделяются на стеке, их адреса близки. Go может оптимизировать это размещение, так как размер массива известен во время компиляции.

2. Базовый массив начинается на стеке, затем перемещается в кучу.

func main() {
slice := make([]int, 0, 3)
println("slice:", slice, "- slice addr:", &slice)

slice = append(slice, 1, 2, 3)
println("slice full cap:", slice)

slice = append(slice, 4)
println("slice after exceed cap:", slice)
}


В этом случае адрес базового массива меняется, когда срез превышает свою емкость. Это означает, что массив теперь находится в куче.

3. Базовый массив сразу выделяется в куче.

Если емкость среза больше 64 КБ, базовый массив будет выделен в куче, как видно в следующем примере:

func main() {
sliceA := make([]int, 64 * 1024)
sliceB := make([]int, 64 * 1024 + 1)
println("sliceA:", sliceA)
println("sliceB:", sliceB)
}


В результате массив для sliceA находится на стеке, а для sliceB — в куче.

🤔 Как избежать выделения памяти в куче?

Лучший способ — заранее оценить необходимую емкость среза, используя make() с установленной емкостью. Это уменьшит вероятность дополнительных выделений памяти. Также можно использовать sync.Pool для повторного использования массивов.
8👍6🔥2
💬 Что такое процесс, системные вызовы и прерывания?

Процесс представляет собой абстракцию ОС, инкапсулирующую ресурсы определенной программы. Чаще всего под процессом понимают отдельно запущенное приложение и его компоненты: стек, регистры, открытые файлы, переменные и так далее. Каждый процесс имеет свое уникальное адресное пространство, контекст выполнения и как минимум один поток — сущность ОС для параллельного выполнения различных задач. Адресное пространство — это набор адресов, используемых процессом для обращения к памяти.

Потоками выполнения можно управлять с помощью системных вызовов и механизма прерываний. Системные вызовы предоставляют интерфейс между пользовательским процессом и ОС для обеспечения ввода / вывода, управления файлами / памятью, доступа к системным объектам.

Механизм прерываний используется для оповещения ОС о внешних событиях и передачи управления конкретному обработчику. В UNIX-подобных системах прерывания реализуются при помощи специальных сигналов из стандарта POSIX.
👍101
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

Напоминаем, что у нас есть бесплатный курс для всех, кто хочет научиться интересно писать — о программировании и в целом.

Что: семь модулей, посвященных написанию, редактированию, иллюстрированию и распространению публикаций.

Для кого: для авторов, копирайтеров и просто программистов, которые хотят научиться интересно рассказывать о своих проектах.

👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
👍1
💬 В чем суть нового пакета unique, добавленного в Go 1.23?

Пакет unique предоставляет инструменты для канонизации значений (interning/hash-consing). Это означает, что дубликаты одного и того же значения будут храниться в памяти только один раз.

Главная идея заключается в том, что с помощью функции Make[T] можно создать специальную ссылку (объект типа Handle[T]) на каноническое представление значения.

Это помогает оптимизировать использование памяти, т. к. одинаковые значения больше не будут занимать лишнее место в памяти.

👉 Подробнее
👍13
💬 Существуют ли в Go правила по расположению и наименованию файлов и функций, предназначенных для тестрования?

Файлы с тестами должны находиться в одном пакете с тестируемыми функциями или в соответствующем пакете с суффиксом _test. Название файла с тестами должно оканчиваться на _test.go.

Название тестирующей функции должно начинаться префиксом Test и далее содержать название тестируемой функции. Тест заканчивается в тот момент, когда тестирующая функция возвращает или вызывает один из методов: FailNow, Fatal, Fatalf, SkipNow, Skip, Skipf. Стоит учитывать, что они могут вызываться только из горутины, выполняющей тестирующую функцию.
7👍4
🆒 Дарим наш курс за ответ на задачу

В предверии дня программиста проводим конкурс: решите нашу задачу на тему программирования — рандомно выберем победителя


Подробные условия:
➡️ Решаем задачу со следующего поста
➡️ Решение присылаем в бота @ProglibContest_bot
➡️ Рандомно среди правильных ответов разыгрываем курс на выбор

Курсы на выбор:
🔵 Архитектуры и шаблоны программирования
🔵 Основы программирования на Python
🔵 Базовые модели ML и приложения
🔵 Frontend Basic: принцип работы современного веба

Таймлайн:
11-12 сентября — принимаем ответы
⬇️
13 сентября — подводим итоги
Please open Telegram to view this post
VIEW IN TELEGRAM
🥱1
❗️Задача для конкурса в честь дня программиста

Условие:

Даны две строки s и f (начальная и конечная) и словарь D (набор слов).

Нужно определить, можно ли преобразовать s в f, используя только слова из словаря D. При этом каждое преобразование должно менять только один символ, а длина слова должна оставаться неизменной. Если преобразование возможно, нужно найти кратчайшую последовательность таких преобразований и вернуть ее длину. Если преобразование невозможно, вернуть "Преобразование невозможно".

Пример ввода 1:
    D = ["cat", "cot", "dot", "dog", "bat", "dag"]
    s = "cat"
    t = "dog"

Вывод:
Минимальное количество шагов для преобразования 'cat' в 'dog': 3

Пример ввода 2:
    D = ["cat", "cot", "bat"]
    s = "cat"
    t = "dog"

Вывод:
Минимальное количество шагов для преобразования 'cat' в 'dog': Преобразование невозможно
Please open Telegram to view this post
VIEW IN TELEGRAM
👍4🔥1😁1🥱1