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

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

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

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
💬 В Go 1.21 появились аналоги sync.Once. Какие именно и для чего они предназначены?

🔸 OnceFunc: функция, которая оборачивает другую функцию так, что та выполнится только один раз. Например, если обёртку wrapper() вызвать несколько раз, внутренняя функция запустится только при первом вызове. Удобно для случаев, когда необходимо гарантировать, что операция выполняется строго один раз, но хочется иметь удобный многократный интерфейс вызова.
🔸 OnceValue[T]: используется для функций, возвращающих одно значение. Это полезно для кеширования результата тяжёлой операции, например загрузки конфигурации, чтобы каждый вызов возвращал тот же результат, экономя ресурсы.
🔸 OnceValues[T, K]: это расширение, позволяющее возвращать несколько значений, включая ошибки, что упрощает обработку потенциальных ошибок во время первого вызова функции. Все последующие вызовы вернут закешированный результат (вместе с ошибкой, если она была).
👍23
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

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

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

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

👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
⚒️ sync.Map в Go: правильный инструмент для правильной работы

Оказывается, sync․Map под капотом поддерживает две мапы, что может быть неидеально, если вы часто добавляете или удаляете ключи.

Читайте продолжение серии статей Phuong Le про сложные аспекты Go на простых иллюстрациях👇

👉
Читать
👉
Другие статьи в серии:
• Go sync.Mutex: нормальный/starvation режим
• Go sync.WaitGroup и проблема выравнивания
• Go sync.Pool и механика, стоящая за ним
• Go sync.Cond, самый недооцененный механизм синхронизации
• Пакет singleflight
👍3🤔1
💬 Как канонизировать строки для экономии памяти в Go?

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

1️⃣ Канонизация строк при их совпадении

if str1 == str2 {
str1 = str2 // освобождаем базовый блок памяти str2
}


Вот пример реализации для канонизации строк в слайсе:
func CanonicalizeStrings(ss []string) {
type S struct {
str string
index int
}
var temp = make([]S, len(ss))
for i := range temp {
temp[i] = S {
str: ss[i],
index: i,
}
}

for i := 0; i < len(temp); {
var k = i+1
for j := k; j < len(temp); j++ {
if temp[j].str == temp[i].str {
temp[j].str = temp[i].str
temp[k], temp[j] = temp[j], temp[k]
k++
}
}
i = k
}

for i := range temp {
ss[temp[i].index] = temp[i].str
}
}


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

2️⃣ Использование unique.Handle из Go 1.23

В Go 1.23 добавлена возможность использовать unique.Handle для удобной канонизации строк.

import "unique"

func CanonicalizeString(s string) string {
return unique.Make(s).Value()
}

func CanonicalizeStrings(ss []string) {
for i, s := range ss {
ss[i] = CanonicalizeString(s)
}
}


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

Примечание: метод unique.Make не всегда подходит для всех ситуаций. Функция unique.Make выделяет блок памяти для каждой уникальной строки. Если некоторые неравные строки, подлежащие канонизации, уже делят один и тот же блок памяти, unique.Make выделит новый блок памяти для каждой из строк, что может привести к увеличению использования памяти (вместо экономии).
👍11
💬 В Go есть функция runtime.SetFinalizer, позволяющая привязать финализатор к объекту. Как она работает и в каких случаях использование финализаторов может быть небезопасным? Приведите пример ситуации, в которой финализатор может не сработать.

runtime.SetFinalizer позволяет привязать функцию (финализатор) к объекту, которая будет выполнена, когда сборщик мусора сочтёт объект неиспользуемым. Финализатор запускается сборщиком мусора, но его выполнение зависит от цикла GC, поэтому точное время выполнения не гарантируется.

Использование финализаторов может быть небезопасным из-за нескольких факторов:
1. Финализаторы могут сработать не сразу после того, как объект станет неиспользуемым, а в зависимости от цикла GC.
2. Tiny objects: объекты размером менее 16 байт и без указателей (так называемые "tiny objects") могут группироваться вместе, и если хотя бы один объект в группе ещё используется, финализаторы для остальных объектов могут не сработать.
3. Ограничение на привязку к началу блока памяти: финализатор можно установить только для указателя, указывающего на начало блока памяти объекта. Если привязать финализатор к внутреннему полю структуры, программа завершится с ошибкой.

В следующем примере FourBytes является "tiny object", и финализатор может не сработать, если другие объекты из этой же группы продолжают использоваться:

type FourBytes struct {
A byte; B byte; C byte; D byte
}

func final() {
a := &FourBytes{}
runtime.SetFinalizer(a, func(a *FourBytes) {
fmt.Println("Финализатор FourBytes вызван")
})
}

func main() {
final()
runtime.GC()
time.Sleep(time.Millisecond)
}


В этом коде финализатор может либо сработать, либо нет, в зависимости от того, как Go управляет группой маленьких объектов. Это делает использование финализаторов в Go непредсказуемым, и в большинстве случаев рекомендуется использовать явное освобождение ресурсов с методами, такими как Close или Dispose.
👍8🤔1
💬 Какие ограничения у традиционного механизма TCP Keepalive в современной архитектуре и как работает Keepalive в контексте межсервисного взаимодействия?

Традиционный механизм TCP Keepalive работает на 4-м уровне модели OSI и позволяет двум узлам поддерживать активное соединение, периодически отправляя друг другу сигналы. Когда узел получает такой сигнал (keepalive probe), он отвечает сообщением ACK, подтверждая свою доступность. Если ответ не приходит в течение заданного времени, узел предполагает, что соединение потеряно. Это эффективно в традиционных сетях.

Однако в современной архитектуре с использованием виртуализации, контейнеризации и прокси-серверов механизм TCP Keepalive имеет ограничение. Он проверяет состояние ближайшего посредника (например, прокси), а не конечного узла, что делает его ненадёжным для сложных сетей. В такой ситуации TCP Keepalive необходимо настраивать на каждом уровне (клиент, прокси и сервер) для гарантии доступности конечного узла.

👉 Подробнее
7👍1
Forwarded from Библиотека программиста | программирование, кодинг, разработка
🔀 Команды git merge и git rebase: преимущества, недостатки и ключевые различия

Один из ключевых аспектов работы с системой контроля версий Git — перенос изменений из одной ветки в другую. Для этого существует два основных инструмента: git merge и git rebase.

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

🔗 Читать статью
🔗 Зеркало
👍4
💬 Какой способ лучше использовать в Go для проверки пустой строки: s != "" или len(s) == 0? В чем разница между этими подходами?

Оба способа корректны и часто используются в Go. Однако предпочтительнее использовать s != "", так как это делает код более читаемым и сразу показывает, что s — это строка.

Использование len(s) == 0 также работает, но это более универсальный способ, который подходит для проверки пустоты слайсов, мап и других типов данных, поэтому может быть менее очевидно, что s — строка.
18👍1
💬 Как json.Unmarshal обрабатывает совпадения ключей в JSON при разном регистре, и какой результат будет при наличии нескольких ключей, отличающихся только регистром?

Функция json.Unmarshal при декодировании JSON-сообщений в структуру Go сначала пытается найти точное совпадение ключа. Если точное совпадение не найдено, она принимает ключи, совпадающие с именем поля структуры без учёта регистра.

Если в JSON присутствуют несколько ключей, которые отличаются только регистром, json.Unmarshal выберет последнее упомянутое значение с учётом регистра. Например, если в JSON имеются ключи "HTML" и "html", то при декодировании в поле HTML структуры будет записано значение из последнего из них.

В приведённом ниже коде JSON содержит два ключа "HTML" и "html" с разными значениями, но функция Unmarshal записывает значение из последнего ключа ("bar") в поле HTML структуры:

package main

import (
"encoding/json"
"fmt"
)

type T struct {
HTML string `json:"HTML"`
}

var s = `{"HTML": "foo", "html": "bar"}`

func main() {
var t T
if err := json.Unmarshal([]byte(s), &t); err != nil {
fmt.Println(err)
return
}
fmt.Println(t.HTML) // bar
}


Таким образом, при наличии нескольких ключей с одинаковым именем, но разным регистром, json.Unmarshal предпочтёт последнее значение.
👍161🥰1
Самые полезные каналы для программистов в одной подборке!

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

🔥Для всех

Библиотека программиста — новости, статьи, досуг, фундаментальные темы
Книги для программистов
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 запрещена на территории РФ
💬 Как интерфейс io.WriterTo оптимизирует передачу данных в Go и как io.Copy() решает, какой метод использовать?

Интерфейс io.WriterTo позволяет объекту-источнику напрямую записывать данные в объект-получатель через метод WriteTo(w Writer). Это устраняет необходимость промежуточного буфера, делая передачу данных более эффективной.

io.Copy() проверяет, реализует ли объект-источник интерфейс WriterTo или объект-получатель интерфейс ReaderFrom:
🔸 Если источник реализует WriterTo, вызывается WriteTo().
🔸 Если получатель реализует ReaderFrom, вызывается ReadFrom().
🔸 Если ни один из интерфейсов не реализован, используется внутренний буфер (по умолчанию 32 КБ).

Этот механизм позволяет сократить количество операций копирования и ускорить передачу данных, особенно для оптимизированных системных вызовов, таких как sendfile в Linux.
👍10
💬 Почему для генерации ключей в Go нельзя использовать math/rand, и как правильно сгенерировать безопасный ключ?

1. Без явного вызова rand.Seed() генератор math/rand всегда возвращает одну и ту же последовательность чисел.
2. Если использовать time.Now().UnixNano() как seed, доступно всего несколько бит энтропии, что делает последовательности легко предсказуемыми.
3. math/rand не подходит для криптографических задач, так как его алгоритм детерминированный и может быть взломан.

crypto/rand Reader — альтернативный вараинт , а если нам нужен текст, можно вывести его в шестнадцатеричном формате или в формате base64:

import (
"crypto/rand"
// "encoding/base64"
// "encoding/hex"
"fmt"
)

func Key() string {
buf := make([]byte, 16)
_, err := rand.Read(buf)
if err != nil {
panic(err) // out of randomness, should never happen
}
return fmt.Sprintf("%x", buf)
// or hex.EncodeToString(buf)
// or base64.StdEncoding.EncodeToString(buf)
}
👍223
💬 Какой подход лучше использовать для объявления пустого среза в Go и почему?

Предпочтительнее использовать var t []string вместо t := []string{}. Первый вариант объявляет срез как nil, в то время как второй вариант создаёт не-nil срез нулевой длины. Они функционально эквивалентны — их len и cap равны нулю, — но стиль с nil-срезом считается предпочтительным.

Важно учитывать, что есть ситуации, когда предпочтителен не-nil срез с нулевой длиной. Например, при кодировании JSON: nil-срез кодируется как null, а []string{} — как пустой JSON-массив [].
👍17
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

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

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

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

👉Материалы регулярно дополняются, обновляются и корректируются. А еще мы отвечаем на все учебные вопросы в комментариях курса.
👍1
🤔🎄🎁 Какой подарок вы бы хотели на Новый год?

Да, начинать готовиться никогда не рано 😉

#интерактив
🤔1
💬 Почему копирование структур в Go может привести к неожиданным результатам? Приведите пример.

Копирование структур может быть проблематичным, если структура содержит указатели или срезы, которые при копировании продолжают ссылаться на ту же область памяти, что и оригинал. Например, структура bytes.Buffer содержит срез []byte. Если скопировать объект Buffer, методы, вызванные на копии, могут изменять данные в оригинале, так как оба объекта используют одну и ту же память.

package main

import (
"bytes"
"fmt"
)

func main() {
// Создаем оригинальный буфер
original := bytes.Buffer{}
original.WriteString("Hello")

// Копируем буфер
copyBuffer := original

// Добавляем данные в копию
copyBuffer.WriteString(", World!")

// Проверяем содержимое оригинала
fmt.Println(original.String()) // Вывод: "Hello, World!"
}


В этом примере срез []byte в копии copyBuffer ссылается на тот же массив, что и в оригинале original. Поэтому изменения в одном буфере затрагивают другой.
👍13
🦫 Самоучитель по Go для начинающих. Часть 17. Основы сетевого программирования. Стек TCP/IP. Сокеты. Пакет net

В этой части самоучителя мы погрузимся в мир сетевого программирования, изучим его основные концепции и инструменты. Начнем с рассмотрения принципов работы компьютерных сетей и их архитектуры, познакомимся с протоколами TCP и IP, лежащими в основе стека TCP/IP.

Затем детально изучим сокеты и их роль в сетевом взаимодействии. Особое внимание будет уделено пакету net, который предоставляет удобные инструменты для реализации сетевых приложений.

👉 Читать гайд

👩‍💻 Остальные части в серии:

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. Конкурентность. Горутины. Каналы
16. Тестирование кода и его виды. Table-driven подход. Параллельные тесты
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥6
👨‍💻🚀 Тест: насколько ты продвинутый разраб?

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

👉 Ворваться
🤩1
💬 Почему добавление элементов в nil-срез работает, а добавление в nil-мапу вызывает панику?

В Go срезы и тип map работают по-разному:

1. Срезы:
🔸 nil-срез — это валидный срез с нулевой длиной (len == 0) и нулевой ёмкостью (cap == 0).
🔸 Когда мы вызываем append() на nil-срезе, Go выделяет новую память и создаёт срез с достаточной ёмкостью для хранения новых элементов. Поэтому добавление элементов в nil-срез работает без ошибок.

Пример:
var a []int
a = append(a, 4, 5, 6) // Создаётся новый срез в памяти
fmt.Println(a) // [4 5 6]


2. Тип map
🔸 nil-мапа неинициализирована и не имеет памяти для хранения пар ключ-значение.
🔸 Любая попытка добавить элемент в nil-мапу вызовет панику, так как мапа не готова к использованию.
🔸 Для работы с мапой её нужно явно инициализировать с помощью функции make.

Пример:
var m map[int]int
// m[1] = 1 // Вызовет панику
m = make(map[int]int)
m[1] = 1 // Теперь работает
👍142