Библиотека Go для собеса | вопросы с собеседований
6.88K subscribers
225 photos
7 videos
1 file
435 links
Вопросы с собеседований по Go и ответы на них.

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

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

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
💡 Одной из идиоматических практик Go является концепция

return early, return often


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

Это делает код более читабельным и простым в сопровождении.

#go #tip by Matt Boyle
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5🥱3
💬 Каков минимальный и максимальный вес горутин?

Минимальный вес горутины в Go составляет ~2 КБ, что является начальным размером стека для каждой горутины. Этот размер может динамически увеличиваться и уменьшаться в зависимости от потребностей программы.

Максимальный размер стека горутины зависит от архитектуры системы: 1 ГБ для 64-разрядной архитектуры, 250 МБ — для 32-разрядной.
🔥19
🤔 Где искать библиотеки и инструменты для своих проектов?

🧰 Подборка для Go-разработчика:

🔗 pkg.go.dev

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

🔗 GitHub

Вводите в поисковую строку language:go + свой запрос и анализируете результаты.

🔗 Awesome Go

Один из самых старых и самых поддерживаемых кураторских списков по Go.

🔗 Libhunt.com

Коллекция Go-проектов, отфильтрованных по количеству упоминаний, звезд или другим критериям.

🔗 go-recipes

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

#tip
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥732👍2
💬 Как получить из среза массив и для чего это может быть нужно?


1. С использованием unsafe:

package main

import (
"fmt"
"unsafe"
)

func main() {
slice := []int{1, 2, 3}
arrayPtr := (*[3]int)(unsafe.Pointer(&slice[0]))
fmt.Println(*arrayPtr)
}


2. С использованием copy:

package main

import "fmt"

func main() {
slice := []int{1, 2, 3}
var array [3]int
copy(array[:], slice)
fmt.Println(array)
}


Такое преобразование может потребоваться, когда мы хотим использовать срез как ключ в типе map.

Поскольку в Go ключи мапы должны быть comparable, мы можем использовать массив с фиксированным размером вместо среза.
🤔9👍3
💬 Что такое inode в Linux?

🔸 Inode (Index Node) — это структура данных, используемая файловой системой для хранения информации о файле или директории, включая права доступа, информацию о владельце, группе, размере, временных метках создания и изменения, а также указатели на блоки данных на диске, где хранится само содержимое файла.

🔸 Директории — это тоже inode типа директория, в которых вместо содержимого файла содержится список имён файлов и номера их inode. Корневая директория в Ext4 имеет номер inode — 2.

🔸 Inode имеют ограниченный размер, поэтому количество файлов или каталогов, которые могут быть созданы в файловой системе, ограничено.
6🥱5🔥3👍2
💬 Что такое шардирование и для чего оно предназначено?

Шардирование (или шардинг) — это разделение хранилища на несколько независимых частей, шардов. Шардирование — это не репликация, в случае которой выделенные экземпляры базы данных являются не составными частями общего хранилища, а копиями друг друга.

🔹 Виды шардинга: вертикальное и горизонтальное.

🔹 Методы шардинга: хешированное, диапазонное, круговое и динамическое.

🔹 Способы шардирования: средствами БД, надстройками к БД и клиентскими средствами.
👍5
💬 Как в Go обрабатываются операции ввода-вывода файлов?

В Go для работы с файлами и операциями ввода-вывода используется пакет os для открытия, создания, чтения, записи и закрытия файлов, а также пакет io или bufio для более эффективного ввода-вывода с буферизацией.

📌 Открытие и чтение файла

Для чтения файла сначала его нужно открыть с помощью функции os.Open(), а затем можно использовать io или bufio для чтения содержимого:

package main

import (
"bufio"
"fmt"
"log"
"os"
)

func main() {
file, err := os.Open("example.txt")
if err != nil {
log.Fatal(err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
for scanner.Scan() {
fmt.Println(scanner.Text())
}

if err := scanner.Err(); err != nil {
log.Fatal(err)
}
}


📌 Создание, запись в файл и добавление данных в файл

Для создания файла используется функция os.Create(), а для записи — метод Write() или WriteString() из пакета os. Чтобы дополнить файл, его нужно открыть с опциями os.O_APPEND и os.O_WRONLY.
👍52
💬 Что такое context switching в Go?

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

Планировщик Go использует модель M:N, где множество горутин (G) распределяются на меньшее количество потоков операционной системы (M), привязанных к логическим процессорам (P), и опирается на кооперативный планировщик для переключения контекста на основе явных событий, таких как синхронизация, системные вызовы и операции ввода-вывода.

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

👉 Подробнее
👍71
💬 Какие кейсы использования default в select?

Использование default в select в Go обеспечивает неблокирующую операцию. Если все другие каналы в select блокированы, выполнение сразу переходит к default, позволяя программе продолжить выполнение без ожидания.

📌 Это особенно полезно для:

☑️ Реализации таймаутов или опроса с немедленным возвратом, когда операции с каналами не готовы.
☑️ Создания циклов обработки событий, где default может обрабатывать фоновые задачи или проверки состояния, не прерывая основной поток выполнения.
🔥8
💬 Что такое NaN и почему NaN не равно NaN?

NaN означает "Not a Number" (не число) и представляет собой специальное значение во многих системах с плавающей запятой, используемых в языках программирования, включая Go, для обозначения результата операций, которые не могут быть определены в терминах числового значения.

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

Согласно стандарту IEEE 754, который определяет арифметику плавающей запятой, любая операция, возвращающая NaN, не должна быть равна никакому числу, включая само NaN. Это правило подчеркивает тот факт, что NaN обозначает неопределенность или результат, который не является числовым значением, и следовательно, сравнение на равенство (или неравенство) с другими числами или даже с самим NaN не имеет смысла, так как неопределенность не может быть равна (или не равна) чему-либо конкретному.
👍172
💬 Если в функции Go есть return, обязательно ли она вернет то, что указано в операторе?

🔸 Если в функции указан return, то она должна вернуть значение(-я), соответствующие её сигнатуре.

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

🔸 Если функция не имеет возвращаемых значений (то есть, её сигнатура не включает возвращаемые типы), использование return просто завершает выполнение функции. В таком случае, return не возвращает никакого значения.
👍6🤔61
🧑‍💻 Статьи для IT: как объяснять и распространять значимые идеи

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

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

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

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

Tickers в Go предназначены для выполнения повторяющихся действий через равные промежутки времени.

Tickers используют каналы Go для отправки сигнала по истечении каждого интервала времени.

Реализовать ticker на Go можно с использованием пакета time. Простой пример использования:


package main

import (
"fmt"
"time"
)

func main() {
ticker := time.NewTicker(1 * time.Second)
defer ticker.Stop()

for {
select {
case <-ticker.C:
fmt.Println("Tick at", time.Now())
// ...
}
}
}


В примере создаётся ticker, который «тикает» каждую секунду. В бесконечном цикле программа ожидает сигнала от ticker.C, канала тикера. Каждый раз, когда тикер отправляет сигнал в свой канал (то есть каждую секунду), программа выполняет код внутри case <-ticker.C, в данном случае печатая текущее время.
👍25
-35% на полугодовой курс по алгоритмам!

🌟 Алгоритмы и структуры данных🌟

23 390 рублей 35 990 рублей до 1 апреля

Курс для тех, кто хочет научиться работать с алгоритмами, подготовиться к собеседованию крупную IT-компанию и начать брать более сложные проекты.

🔥 Переходите и активируйте вводные занятия курсаhttps://proglib.io/w/5a72cc41

Вас ждут:

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

– бессрочный доступ к обучению

– поддержка преподавателя в чате

А также очень харизматичный спикер из Яндекса 🙌🏻
💬 Для чего в приведенном коде предназначена конструкция "_ struct{}"?

Конструкция _ struct{} используется для предотвращения создания литералов структур без именованных полей при инициализации ProgInfo.

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

В Go, когда мы инициализируем структуру без указания имён полей, например:


info := ProgInfo{0, 1, 2, 3}


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

Добавление поля _ struct{} делает такую инициализацию невозможной, требуя от разработчика использовать именованные литералы, где каждое значение присваивается конкретному имени поля:


info := ProgInfo{
Flags: 0,
Reguse: 1,
Regset: 2,
Regindex: 3,
}
👍75😁52
⚡️Proglib запускает каналы про нейросети

По каждому направлению отдельно! А именно:

Библиотека нейрозвука — здесь все, связанное с транскрибацией, синтезом речи, ИИ-музыкой
Библиотека нейротекста — классические ИИ-помощники вроде ChatGPT, Gemini, Bing
Библиотека нейровидео — здесь пишем про нашумевшую Sora AI, а также про Runway ML, дипфейки и другие видеотехнологии
Библиотека нейрокартинок — генерируем изображения и рассказываем про Midjourney, DALL-E, Stable Diffusion
⭐️Библиотека робототехники и беспилотников — наконец, тут мы рассказываем не столько про ИИ, сколько про роботов, беспилотные технологии и интернет вещей

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

Подписывайтесь!
💬 В чем разница между методами Time.Sub() и Time.Add() пакета time?

Ключевое отличие между методами Time.Add() и Time.Sub() в пакете time заключается в их параметрах и возвращаемых значениях. Time.Add() принимает параметр Duration и возвращает значение Time, в то время как Time.Sub() принимает параметр Time и возвращает Duration.

💬 Почему они оба не принимают Duration и не возвращают Time?

Причина в том, что Time.Add() может обрабатывать отрицательные аргументы, эффективно выполняя операцию вычитания. Следовательно, не имело бы смысла иметь другой метод Time.Sub(), который также принимает Duration.

Методы Time.Add() и Time.Sub() служат разным целям и имеют различные сигнатуры для обработки конкретных юзкейсов:

package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()

newTime := now.Add(2 * time.Hour)
fmt.Println("Time after 2 hours:", newTime)
newTime = now.Add(-2 * time.Hour)
fmt.Println("Time before 2 hours:", newTime)

duration := newTime.Sub(now)
fmt.Println("Duration newTime to now:", duration)
}


Как показано в примере, Time.Add() используется для добавления или вычитания продолжительности из временного значения, в то время как Time.Sub() используется для вычисления продолжительности между двумя временными значениями.
👍133