Библиотека 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:
package main

import "fmt"

type InvertedIndex map[string][]int

func addToIndex(index InvertedIndex, term string, docID int) {
index[term] = append(index[term], docID)
}

func main() {
index := make(InvertedIndex)

// Добавление в индекс
addToIndex(index, "hello", 1)
addToIndex(index, "world", 1)
addToIndex(index, "go", 2)

// Печать результата
fmt.Println(index)
}


В этом примере создается обратный индекс, где слово «hello» встречается в документе 1, «world» — в документе 1, а «go» — в документе 2.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1
Как вам вопросы прошедшей недели

Оцените их по шкале 🔥,❤️,👍,😢, 🥱,
где 🔥 — это супер, а 🥱 — это скучно.

Также приветствуется фидбек в комментах.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍22🔥13🥱84
This media is not supported in your browser
VIEW IN TELEGRAM
Добейте 7 бустов, плиз, иначе вопросов с собесов не будет 🚬
Please open Telegram to view this post
VIEW IN TELEGRAM
😢13😁5
Что такое паттерн «Декоратор» и как его реализовать

Декоратор — это способ добавить новую логику к объекту, не меняя его код. В Go это удобно делать через интерфейсы. Один объект «оборачивает» другой и выполняет дополнительную работу до или после вызова.

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

Простой пример: логирование вызова метода
type Handler interface {
Handle(msg string) string
}

type SimpleHandler struct{}

func (h SimpleHandler) Handle(msg string) string {
return "Handled: " + msg
}


Теперь сделаем обёртку:
type LoggingHandler struct {
next Handler
}

func (l LoggingHandler) Handle(msg string) string {
fmt.Println("Запрос:", msg)
result := l.next.Handle(msg)
fmt.Println("Ответ:", result)
return result
}


Использование:
func main() {
base := SimpleHandler{}
withLog := LoggingHandler{next: base}

fmt.Println(withLog.Handle("тест"))
}


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
17🔥3👍2
В чем особенность неиспользуемых переменных и импортов в Go

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

➡️ Если в коде есть неиспользуемая локальная переменная, такой код не скомпилируется.
package main

import "fmt"

func main() {
x := 10
fmt.Println("Hello, World!")
}

Компилятор выдаст ошибку: x declared but not used

➡️ Если функция возвращает значения, но значения не используются, компилятор не выдаст ошибку.
Однако если значения присваиваются переменным, которые затем не используются, это вызовет ошибку компиляции.
package main

import "errors"

func doSomething() (int, error) {
return 42, errors.New("an error occurred")
}

func main() {
doSomething() // Это допустимо
result, err := doSomething() // Ошибка, так как result и err не используются
}


➡️ Если в коде присутствует импорт, который не используется, компилятор выдаст ошибку: "math" imported and not used
package main

import "math" // Ошибка, импорт не используется

func main() {
// Ничего не делаем
}


Правило не касается неиспользуемых параметров функций и глобальных переменных. Код скомпилируется:
package main

import "fmt"

var globalVar int // Глобальная переменная, которая не используется

func greet(name string, age int) { // Параметры функции также могут не использоваться
fmt.Println("Hello,", name)
}

func main() {
greet("Alice", 25) // Параметры функции 'name' и 'age' не используются
fmt.Println("Hello, World!")
}


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👾5👍42🥱1
Если вы зашьёте в код приватный токен и скомпилируете код — можно ли будет извлечь токен

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

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

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

Так что да, токен можно будет прочитать.

На практике, токены или пароли должны быть хранены в защищённых местах, например:

• В переменных окружения.

• В защищённых хранилищах секретов, например, HashiCorp Vault, AWS Secrets Manager, Azure Key Vault.

• Шифрованных конфигурационных файлах.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍72
Как создать простой веб-сервер на Go с использованием стандартной библиотеки

Базовый пример:
package main

import (
"fmt"
"net/http"
)

func helloHandler(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hello, World!")
}

func main() {
http.HandleFunc("/hello", helloHandler)
http.ListenAndServe(":8080", nil)
}


1️⃣ Подключаем fmt для форматированного вывода и net/http для работы с HTTP.

2️⃣ Обработчик запросов: функция helloHandler отвечает на все запросы сообщением "Hello, World!".

3️⃣ С помощью http.HandleFunc регистрируем обработчик на корневой эндпоинт ("/hello").

4️⃣ http.ListenAndServe(":8080", nil) запускает сервер на порту 8080.

➡️ После запуска кода при переходе по адресу http://localhost:8080/hello вы получите ответ: "Hello, World!"

Также можно использовать http.FileServer:
package main

import "net/http"

func main() {
port := ":8080"
handler := http.FileServer(http.Dir("."))
http.ListenAndServe(port, handler)
}

Аналог python -m http.serverраздаёт текущую директорию по HTTP.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
😁52
Чем является rune в Go и как он связан с символами Unicode

Работа со строками в Go не ограничивается ASCII-символами, в текстах часто встречаются символы других языков и эмодзи. Для корректной обработки таких символов используется тип rune.

rune — это псевдоним для int32, предназначенный для хранения Unicode-кода одного символа.

При переборе строки с помощью конструкции for range, Go обходит строку по символам Unicode, автоматически преобразуя её в последовательность rune.

Примеры:

Объявление и инициализация руны:
var r rune = 'A'


Преобразование строки в срез рун:
s := "Привет"
runes := []rune(s)


Итерация по рунам в строке:
for _, r := range "Привет" {
fmt.Printf("%c ", r)
}
// Вывод: П р и в е т


Обратное преобразование среза рун в строку:
runes := []rune{'П', 'р', 'и', 'в', 'е', 'т'}
s := string(runes) // "Привет"


Получение Unicode-кода руны:
r := 'A'
code := int32(r) // 65


Проверка длины строки в рунах:
s := "Привет"
length := utf8.RuneCountInString(s) // 6


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍102🔥1
Как Go реализует обработку ошибок

1️⃣ Явная обработка — в Go нет исключений.
Функции, которые могут завершиться с ошибкой, возвращают её как отдельное значение наряду с результатом.


2️⃣ Множественные возвращаемые значения — стандартный шаблон:
val, err := someFunction()
if err != nil {
// обработка ошибки
}


3️⃣ Кастомные ошибки — через пакет errors можно определять собственные типы ошибок и добавлять к ним полезную информацию.

4️⃣ Обогащение контекста — с Go 1.13 доступны errors.Is, errors.As и fmt.Errorf(... %w ...) для оборачивания ошибок с сохранением исходной причины.
func DoSomething() error {
if err := someOperation(); err != nil {
return fmt.Errorf("someOperation failed: %w", err)
}
return nil
}


5️⃣ Нет finally — очистка ресурсов выполняется через defer.

6️⃣ Panic и recover — используются только для критических непредвиденных ситуаций, например выхода за границы массива.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
4👍2🔥1
Расскажите о механизме мьютексов в Go и укажите существующие типы

Mutex (mutual exclusion — взаимное исключение) — примитив синхронизации для защиты критической секции программы. Он предотвращает гонки данных и deadlock’и, обеспечивая эксклюзивный доступ к ресурсу.

Критическая секция — участок кода, где одновременно может работать только одна горутина.

➡️ sync.Mutexэксклюзивная блокировка
Только одна горутина может захватить мьютекс и получить доступ к ресурсу.
var mu sync.Mutex

func increment() {
mu.Lock()
count++
mu.Unlock()
}

Здесь мы рассматриваем защиту глобальной переменной count при инкременте из множества горутин.

➡️ sync.RWMutex концептуально то же самое, что и Mutex, но дает вам немного больше контроля над памятью.
Позволяет:
RLock — множеству горутин читать одновременно.
Lock — только одному писателю, без читателей.
var mu sync.RWMutex

func set(key, value string) {
mu.Lock()
cache[key] = value
mu.Unlock()
}

func get(key string) string {
mu.RLock()
defer mu.RUnlock()
return cache[key]
}

Дает безопасный доступ к кэшу — много читателей, один писатель.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6🔥1👏1