Библиотека Go для собеса | вопросы с собеседований
5.49K subscribers
141 photos
1 video
1 file
173 links
Вопросы с собеседований по Go и ответы на них.

Список наших каналов: https://t.me/proglibrary/9197
Учиться у нас: https://proglib.io/w/0b524a15

Обратная связь: @proglibrary_feedback_bot

По рекламе: @proglib_adv
Прайс: @proglib_advertising
Download Telegram
💬 Существуют ли в Go правила по расположению и наименованию файлов и функций, предназначенных для тестрования?

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

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

Условие:

Даны две строки 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
📹 Все о массивах и слайсах в Go: видеогайд от Владимира Балуна

⏱️ Таймкоды:

00:00 Введение
00:47 Устройство массивов в Go
01:40 Работа с массивами в Go
10:00 Перемещение массива в стеке
11:29 Итерация по массивам в Go
15:11 Где аллоцируются массивы в Go
17:22 Педедача массива в функцию
18:16 Слайсы в Go
21:34 Реаллокация слайса в Go
24:45 Резервирование памяти под слайс
25:44 Создание слайса без инициализации
27:38 Модификация строк в Go
28:35 Приведение слайсов в строки и обратно без копирования
30:13 Передача слайса в функцию
31:12 Итерация по слайсам в Go
33:55 Оптимизация итерации по слайсам в Go
35:42 Получение слайсов в Go
42:40 Получение слайса из массива в Go
43:15 Конвертация слайса в массив в Go
44:15 Конвертация слайса в указатель на массив в Go
45:02 Указатель на нулевой массив в Go
46:18 Удаление из конца слайса в Go
46:51 Удаление из начала слайса в Go
49:02 Реализация стека и очереди в Go
50:00 Как увеличить размер слайса в Go
50:48 Как уменьшить емкость слайса в Go
54:05 Где аллоцируются слайсы в Go
59:12 Как очистить слайс в Go
01:01:51 В чем разница пустых и нулевых слайсов в Go
01:05:17 Как сравнивать слайсы в Go
01:07:53 Как скопировать данные слайса в Go
01:09:47 Почему функция appeng возвращает слайсв в Go
01:12:39 Потенциальные проблемы с функцией append в Go
01:14:10 Реализация функции append в Go
01:15:32 Утечки памяти при работе со слайсами в Go

📺 YouTube | VK Видео | Дзен | Rutube
Please open Telegram to view this post
VIEW IN TELEGRAM
Go-разработчики часто используют следующую конструкцию:

f, err := os.Create("file.txt")
if err != nil {
return err
}
defer f.Close()


Однако, для файлов с возможностью записи это может быть опасно, так как метод Close() может вернуть ошибку, которая игнорируется при использовании defer.

Ошибки могут возникать на этапе закрытия файла, когда система завершает запись данных на диск. Чтобы избежать потери данных, важно проверять ошибки явным образом:

f, err := os.Create("file.txt")
if err != nil {
return err
}
if _, err := f.Write([]byte("Hello, world!")); err != nil {
f.Close()
return err
}
return f.Close()


Использование defer безопасно для чтения, но для записи стоит быть осторожнее и проверять ошибки вручную.

👉 Подробнее
Самые полезные каналы для программистов в одной подборке!

Сохраняйте себе, чтобы не потерять 💾

🔥Для всех

Библиотека программиста — новости, статьи, досуг, фундаментальные темы
Книги для программистов
IT-мемы
Proglib Academy — тут мы рассказываем про обучение и курсы
Азбука айтишника — здесь мы познаем азы из мира программирования

🤖Про нейросети
Библиотека робототехники и беспилотников | Роботы, ИИ, интернет вещей
Библиотека нейрозвука | Транскрибация, синтез речи, ИИ-музыка
Библиотека нейротекста | ChatGPT, Gemini, Bing
Библиотека нейровидео | Sora AI, Runway ML, дипфейки
Библиотека нейрокартинок | Midjourney, DALL-E, Stable Diffusion

#️⃣C#

Книги для шарпистов | C#, .NET, F#
Библиотека шарписта — полезные статьи, новости и обучающие материалы по C#
Библиотека задач по C# — код, квизы и тесты
Библиотека собеса по C# — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Вакансии по C#, .NET, Unity Вакансии по PHP, Symfony, Laravel

☁️DevOps

Библиотека devops’а — полезные статьи, новости и обучающие материалы по DevOps
Вакансии по DevOps & SRE
Библиотека задач по DevOps — код, квизы и тесты
Библиотека собеса по DevOps — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования

🐘PHP

Библиотека пхпшника — полезные статьи, новости и обучающие материалы по PHP
Вакансии по PHP, Symfony, Laravel
Библиотека PHP для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по PHP — код, квизы и тесты

🐍Python

Библиотека питониста — полезные статьи, новости и обучающие материалы по Python
Вакансии по питону, Django, Flask
Библиотека Python для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Python — код, квизы и тесты

Java

Книги для джавистов | Java
Библиотека джависта — полезные статьи по Java, новости и обучающие материалы
Библиотека Java для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Java — код, квизы и тесты
Вакансии для java-разработчиков

👾Data Science

Книги для дата сайентистов | Data Science
Библиотека Data Science — полезные статьи, новости и обучающие материалы по Data Science
Библиотека Data Science для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Data Science — код, квизы и тесты
Вакансии по Data Science, анализу данных, аналитике, искусственному интеллекту

🦫Go

Книги для Go разработчиков
Библиотека Go разработчика — полезные статьи, новости и обучающие материалы по Go
Библиотека Go для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по Go — код, квизы и тесты
Вакансии по Go

🧠C++

Книги для C/C++ разработчиков
Библиотека C/C++ разработчика — полезные статьи, новости и обучающие материалы по C++
Библиотека C++ для собеса — тренируемся отвечать на каверзные вопросы во время интервью и технического собеседования
Библиотека задач по C++ — код, квизы и тесты
Вакансии по C++

💻Другие каналы

Библиотека фронтендера
Библиотека мобильного разработчика
Библиотека хакера
Библиотека тестировщика
Библиотека разработчика игр | Gamedev, Unity, Unreal Engine
Вакансии по фронтенду, джаваскрипт, React, Angular, Vue
Вакансии для мобильных разработчиков
Вакансии по QA тестированию
InfoSec Jobs — вакансии по информационной безопасности

📁Чтобы добавить папку с нашими каналами, нажмите 👉сюда👈

Также у нас есть боты:
Бот с IT-вакансиями
Бот с мероприятиями в сфере IT

Мы в других соцсетях:
🔸VK
🔸YouTube
🔸Дзен
🔸Facebook *
🔸Instagram *

* Организация Meta запрещена на территории РФ
💬 Назовите кейсы, в которых sync.Cond может быть более подходящим выбором, чем каналы?

1. С каналом мы можем либо отправить сигнал одной горутине, отправив значение, либо уведомить все горутины, закрыв канал, но мы не можем сделать и то, и другое. sync.Cond предоставляет более детальный контроль. Мы можем вызвать Signal(), чтобы запустить отдельную горутину, или Broadcast() чтобы разбудить их все.
2. И мы можем вызывать Broadcast() столько раз, сколько нужно, чего каналы не могут делать, когда они закрыты (закрытие закрытого канала вызовет панику).
3. Каналы не предоставляют встроенного способа защиты shared данных — нам нужно будет управлять этим отдельно с помощью мьютекса. sync.Cond, с другой стороны, предлагает более комплексный подход, объединяя блокировку и сигнализацию в одном пакете (и повышая производительность).
Флаг -cpu можно использовать при запуске тестов Go, чтобы указать список значений GOMAXPROCS, с использованием которых необходимо запустить тесты. Например,
go test -cpu=4,5 


запустит тесты 2 раза. Тесты сначала будут запущены с четырьмя процессорами, а затем второй раз — с пятью.

#tip
💬 Каким образом хранится внутреннее состояние sync.WaitGroup?

Оно хранится в переменной типа atomic.Uint64, которая ключает:

🔸 Counter (старшие 32 бита): эта часть отслеживает количество горутин, которые ожидает WaitGroup. При вызове wg.Add() с положительным значением, счётчик увеличивается, а при вызове wg.Done() — уменьшается на единицу.
🔸 Waiter (младшие 32 бита): отслеживает количество горутин, которые ждут, пока счётчик достигнет нуля. Как только счётчик достигает нуля, все ожидающие горутины разблокируются.

Также есть последнее поле — sema uint32, это внутренний семафор, управляемый рантаймом Go.
🙌 Хардкорный вышмат для тех, кто интересуется ML, AI, DS

Начать с вводных занятий можно здесь, ответив всего на 4 вопроса – https://proglib.io/w/6d9d383b

Что будет на демо?

🔹Вводный урок от CPO курса;

🔹Лекции со всеми преподавателями МГУ по темам: теория множеств, непрерывность функции, основные формулы комбинаторики, матрицы и операции над ними, градиентный спуск;

🔹Практические задания и дополнительные материалы!

⚡️Переходите и активируйте – https://proglib.io/w/6d9d383b
Please open Telegram to view this post
VIEW IN TELEGRAM
💬 Что такое буферизация? Как она реализована в Go?

Скорость операций ввода-вывода значительно повышается, когда данные накапливаются в специальном буфере для их последующего чтения или записи. Такой подход называется буферизацией. Он позволяет сократить количество системных вызовов и улучшить производительность программы.

В Go для буферизации операций ввода-вывода используется встроенный пакет bufio. Он оборачивает io.Reader или io.Writer, создавая новый объект Reader или Writer, соответственно, который также реализует интерфейс, но обеспечивает буферизацию и некоторые улучшения ввода-вывода.
Пакет bufio содержит три основных типа: Reader, Writer и Scanner.
💬 Перечислите кейсы применения iota в Go.

🔸 iota и enums

Мы часто определяем константы в Go для создания списка возможных значений, которые что-то может принимать (это иногда называют enum).

const (
Planet = 0
Star = 1
Comet = 2
Galaxy = 3
// и так далее
)


Конкретные числа 0, 1, 2... здесь не имеют значения. Это просто произвольные значения, с которыми можно сравнивать объекты:

if object.Kind == Planet {
// это планета!
}


🔸 Использование iota с const

Однако поддерживать длинный список таких чисел вручную сложно. Вот где приходит на помощь iota. Это своего рода магическое, постоянно увеличивающееся значение, которое мы можем использовать для присвоения произвольных чисел константам:

const (
Planet = iota // 0
Star // 1
Comet // 2
Galaxy // 3
// ...
)


Мы фактически присваиваем iota каждой константе в списке, но Go позволяет опустить запись = iota после первой константы.

🔸 Начало iota с 1

Также мы можем использовать iota в более сложных выражениях. Например, если мы хотим, чтобы значения начинались с 1, а не с 0:

const (
January = iota + 1
February
March
// ...
)


Здесь значение для January будет 1, для February — 2 и так далее.

🔸 iota игнорирует комментарии

Кстати, можно добавлять комментарии или пустые строки в блок констант, и это не повлияет на значения iota:

const (
Electron = iota // 0
Neutron // 1
Proton // 2
Photon // 3
Gluon // 4
)


🔸 iota, флаги и битовые маски

Ещё одно распространённое применение iota — создание значений для битовых масок. Битовая маска — это способ сравнить число с бинарным значением, чтобы проверить, установлен ли конкретный бит в 1 или 0. Когда используются конкретные битовые значения, их иногда называют флагами, а число, содержащее их, — битовым полем.

Например:

const (
Bit0 = 1 << iota // 1
Bit1 // 2
Bit2 // 4
// ...
)


Оператор << сдвигает биты числа влево на указанное количество позиций. Так как iota увеличивается на единицу для каждой последующей константы, коэффициент сдвига тоже увеличивается на один, поэтому значения, присвоенные константам, продолжают удваиваться.

Теперь можно выполнить побитовое сравнение этих масок с интересующим нас числом:

v := 0b00000010
if v&Bit1 != 0 {
fmt.Println("Looks like bit 1 is set!")
}
// Looks like bit 1 is set!
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

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

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

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

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

• Нулевой срез — это срез, который имеет значение nil, и он не указывает на какой-либо выделенный блок памяти. Его длина и ёмкость равны нулю, а сам срез nil.
• Пустой срез — это срез, который ссылается на существующий, но пустой блок памяти (например, s := make([]int, 0) или s := []int{}). Его длина и ёмкость равны нулю, но сам срез не является nil.

📌 Практическая разница:
• nil-срез полезен для того, чтобы указать отсутствие данных, и в некоторых ситуациях может потребоваться, чтобы срез был именно nil.
• Пустой срез гарантирует наличие выделенной памяти, даже если в нем нет элементов, и его можно безопасно использовать для операций без дополнительной проверки на nil.
💬 Что такое Bound Check Elimination (BCE)? Поддерживает ли Go-компилятор BCE?

Go — язык, защищающий память. При индексации элементов массива/среза/строки и операциях с вложенными срезами рантайм Go проверяет, находятся ли задействованные индексы вне диапазона. Если индекс находится вне диапазона, возникнет паника. Это называется проверкой границ.

Проверки границ обеспечивают безопасную работу кода, с другой стороны, они также замедляют его выполнение. Это компромисс, на который должен пойти безопасный язык.

Начиная с Go toolchain версии v1.7, стандартный компилятор Go начал поддерживать BCE. BCE позволяет избежать некоторых ненужных проверок границ, чтобы стандартный компилятор Go мог генерировать более эффективные программы.
💬 Расскажите о назначении, составляющих, достоинствах и недостатках gRPC.

gRPC (Google Remote Procedure Calling) — система удаленного вызова процедур, разработанная Google. Основное назначение — реализация взаимодействия между микросервисными архитектурами при разработке приложений.

gRPC включает в себя три основных составляющих: стандарт сериализации данных Protocol Buffers (Protobuf), протокол передачи данных HTTP/2 и язык описания интерфейса IDL.

Высокая производительность, бинарный формат хранения данных. Protobuf изначально работает с сериализованными данными, что позволяет эффективно обмениваться информацией по низкоскоростным и слабопроизводительным физическим линиям связи без потерь времени на дополнительные преобразования.
Сложность дебага, ограниченная поддержка браузеров.
💻🔍💼 Кризис IT-рынка: как джуны и кадровый голод меняют правила игры

В условиях нехватки опытных специалистов и наплыва джунов, IT-компании вынуждены искать нестандартные подходы к найму. Рассмотрим основные тренды и стратегии адаптации рынка.

Читать статью

#почитать
Вы создаете приложение, которому необходимо выполнять код через определённый промежуток времени или с регулярными интервалами. Какие пакеты будете использовать?

Go предоставляет для этого time.Timer и time.Ticker.

• Timers: срабатывают один раз по истечении заданного времени.
• Tickers: запускаются повторно с фиксированными интервалами.

Вот как можно использовать функцию time.Timer, чтобы подождать 2 секунды перед выполнением кода:

package main

import (
"fmt"
"time"
)

func main() {
timer := time.NewTimer(2 * time.Second)
<-timer.C
fmt.Println("Timer expired!")
}


а вот и ticker, который запускается каждую секунду:

package main

import (
"fmt"
"time"
)

func main() {
ticker := time.NewTicker(1 * time.Second)
for t := range ticker.C {
fmt.Println("Tick at", t)
}
}
Назовите лучшие практики работы с интерфейсами в Go.

1. Маленькие интерфейсы проще реализовывать и мокать.

type Reader interface {
Read(p []byte) (n int, err error)
}

вместо
type ReadCloser interface {
Read(p []byte) (n int, err error)
Close() error
}


2. Использование интерфейсов в параметрах функций для обеспечения гибкости в реализации.

func CopyData(r Reader, w Writer) error {
buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if err != nil {
return err
}
if n == 0 {
break
}
if _, err := w.Write(buf[:n]); err != nil {
return err
}
}
return nil
}


3. Возврат конкретных типов, когда нужно предоставить полный набор функциональности.

func NewBuffer() *bytes.Buffer {
return &bytes.Buffer{}
}


4. Использование композиции интерфейсов: создание сложных интерфейсов на основе более простых.

type ReadCloser interface {
Reader
Closer
}


5. Избегание чрезмерного использования интерфейсов: преждевременное введение абстракций может усложнить код и сделать его менее читаемым.
📉👩‍💻 Руководство по сборщику мусора Go

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

👉 Читать
Please open Telegram to view this post
VIEW IN TELEGRAM
💬 Можно ли реализовать set на Go?

Set — это структура данных, которая хранит уникальные элементы и позволяет быстро проверять их наличие, добавлять и удалять их, без дубликатов. В Go нет встроенного типа для множеств, но мы можем использовать тип map с ключами нужного типа, а в качестве значения использовать struct{}, который не занимает память:

package main

import "fmt"

// Set — коллекция уникальных элементов
type Set struct {
elements map[string]struct{}
}

// NewSet создает новое множество
func NewSet() *Set {
return &Set{elements: make(map[string]struct{})}
}

// Add добавляет элемент
func (s *Set) Add(value string) {
s.elements[value] = struct{}{}
}

// Remove удаляет элемент
func (s *Set) Remove(value string) {
delete(s.elements, value)
}

// Contains проверяет наличие элемента
func (s *Set) Contains(value string) bool {
_, found := s.elements[value]
return found
}

// List возвращает все элементы в виде среза
func (s *Set) List() []string {
keys := make([]string, 0, len(s.elements))
for key := range s.elements {
keys = append(keys, key)
}
return keys
}

// Пример использования множества
func main() {
set := NewSet()
set.Add("apple")
set.Add("banana")
fmt.Println("Contains 'apple':", set.Contains("apple"))
fmt.Println("Set elements:", set.List())
set.Remove("banana")
fmt.Println("Set after removal:", set.List())
}


Основные операции с множествами:

- Union: создаёт множество, содержащее все элементы из двух множеств.
- Intersection: возвращает множество с элементами, общими для двух множеств.
- Difference: возвращает множество элементов, которые есть в первом множестве, но отсутствуют во втором.

Пример:
set1 := NewSet()
set1.Add("apple")
set1.Add("banana")
set2 := NewSet()
set2.Add("banana")
set2.Add("orange")
unionSet := set1.Union(set2)
fmt.Println("Union:", unionSet.List()) // ["apple", "banana", "orange"]


Производительность: все основные операции с помощью множеств (добавление, удаление, проверка) выполняются за время O(1) благодаря использованию мапы.