Библиотека Go для собеса | вопросы с собеседований
6.98K subscribers
252 photos
10 videos
1 file
611 links
Вопросы с собеседований по Go и ответы на них.

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

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

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

Наши каналы: https://t.iss.one/proglibrary/9197
Download Telegram
Как реализовать собственный формат сериализации для типа и когда это нужно

Собственный формат сериализации задаётся реализацией интерфейса json.Marshaler — то есть методом MarshalJSON() ([]byte, error) у типа.

Это нужно, когда стандартное поведение encoding/json не подходит: особый формат даты, обёртка, маскирование.

Пример:
func (t MyTime) MarshalJSON() ([]byte, error) {
// хотим формат "YYYY|MM|DD"
s := t.Format("2006|01|02")
return json.Marshal(s)
}


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

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

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

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
1🔥103👍1🥱1
Какие параметры принимает json.MarshalIndent, что означают prefix и indent

json.MarshalIndent принимает те же данные, что и Marshal, плюс два строковых параметра prefix и indent, которые управляют только форматированием человекочитаемого JSON.

prefix — строка, которая ставится в начале каждой строки JSON. Обычно пустая, иногда используют для логов.

indent — строка для каждого уровня вложенности: например " " или "\t"

Во всех случаях prefix и indent не влияют на порядок полей и значения, только на внешний вид текста JSON.

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что произойдёт, если тип реализует MarshalJSON, но внутри MarshalJSON сделать рекурсивный вызов json.Marshal над самим собой без обёрток

Если внутри MarshalJSON вызвать json.Marshal на значении того же типа без обёртки, получится бесконечная рекурсия и в итоге паника по переполнению стека.

Как делать правильно

Нужно маршалить не самого себя, а сырой тип без метода, например type alias или обёртку, либо вспомогательную структуру/тип, у которого нет MarshalJSON.

Пример безопасного варианта:
type User struct {
Name string
}

func (u User) MarshalJSON() ([]byte, error) {
type plain User // alias без методов
return json.Marshal(plain(u))
}


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Есть ли гарантия порядка полей в результирующем JSON и нужно ли на него полагаться

Порядок полей в JSON формально не гарантируется и полагаться на него не стоит.

Для struct encoding/json на практике выводит поля в порядке, заданном в определении типа, но это деталь реализации, а не контракт, прописанный в спецификации JSON или строгом API пакета.

Для мап порядок ключей в JSON принципиально не определён: обход мапы в Go сам по себе недетерминирован.

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
В чём разница между runtime.GC() и GOGC=off

Функция runtime.GC() принудительно запускает цикл сборки мусора и блокирует вызывающий горутины до завершения.

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

Переменная окружения GOGC=off полностью отключает автоматический сборщик мусора, эквивалентно установке GOGC в бесконечность.

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

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
WANTED: GO-ДОПРОСИТЕЛЬ

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

Приметы:

— профессионально пишет на Golang (знает, чем он отличается от Java и Python);
— понимает, что на самом деле спрашивают на интервью в бигтех-компаниях;
— обладает талантом методиста и наставника;
— готов монетизировать свой опыт через создание качественного контента.

Условия:

— статус эксперта в Proglib Academy;
— достойная оплата за участие в проектах;
— мощный PR твоего имени в IT-среде.

Признаться во всём

P.S. Твой техлид — Gopher со стажем? Сдай его следствию.
Когда использовать debug.SetGCPercent

debug.SetGCPercent используется для динамической настройки порога запуска сборщика мусора во время выполнения программы, в отличие от статической переменной GOGC.

SetGCPercent(200) снижает частоту GC, но увеличивает память.

SetGCPercent(50) запускает GC чаще с короткими паузами.

SetGCPercent(-1) полностью отключает автоматическую сборку мусоры, это эквивалентно GOGC=off, память растёт без ограничений.

🎁
Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Как sync.Pool помогает снижать давление на GC

sync.Pool снижает давление на GC, переиспользуя временные объекты между циклами сборки мусора вместо постоянных аллокаций новых.

При Get() пул возвращает готовый объект или создаёт новый через New(). После использования Put() возвращает объект в локальный пул.


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что произойдёт, если у структуры есть поле-канал или функция и вы попытаетесь его cмаршалить

При попытке маршала канала в JSON возникнет ошибка:
type MyStruct struct {
Ch chan int
}

data, err := json.Marshal(MyStruct{Ch: make(chan int)})
// error: json: unsupported type: chan int


Функции также не поддерживаются:
type MyStruct struct {
Fn func(int) string
}

data, err := json.Marshal(MyStruct{Fn: func(i int) string { return "" }})
// error: json: unsupported type: func(int) string



🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

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

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

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍83🔥3
Что такое Dead Letter Queue

Dead Letter Queue — это отдельная очередь для обработки сообщений, которые не могут быть успешно обработаны из основной очереди. Это механизм обработки ошибок в системах асинхронной обработки сообщений.

Как это работает

1. Сообщение попадает в основную очередь.
2. Потребитель пытается его обработать.
3. Если обработка не удаётся, то сообщение может быть переотправлено.
4. После определённого количества неудачных попыток сообщение отправляется в DLQ.
5. DLQ хранит эти мёртвые сообщения для анализа и ручной обработки.

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
Объясните, как работает директива //go:generate

//go:generate — это директива препроцессора, которая указывает инструменту go generate на необходимость выполнить определённую команду для автоматической генерации кода.

Директива должна находиться в начале файла после импортов, перед объявлениями:
package main

import "fmt"

//go:generate go run gen.go
//go:generate stringer -type=Status

type Status int

const (
Pending Status = iota
Active
Done
)

func main() {
fmt.Println("Hello")
}


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Что такое netip.Addr и в чём его преимущества перед net.IP

netip.Addr — это тип из пакета net/netip, который представляет IP-адрес. Это современная замена net.IP.

Основные различия

Тип данных:
// net.IP - это срез байтов
type IP []byte

// netip.Addr - это структура с оптимизацией
type Addr struct {
// Внутренняя реализация с компактным хранением
}


Размер в памяти:
import (
"net"
"net/netip"
)

// net.IP
var ip1 net.IP = net.ParseIP("192.168.1.1")
// Размер: от 4 до 16 байт (срез) + 24 байта (заголовок среза) = ~28-40 байт

// netip.Addr
var ip2 netip.Addr = netip.MustParseAddr("192.168.1.1")
// Размер: 16-17 байт (оптимизирован)


Преимущества netip.Addr

Его можно сравнить, а значит использовать как ключ в мапе:
// net.IP нельзя использовать как ключ в map
var m map[net.IP]string // Ошибка компиляции!

// netip.Addr можно использовать как ключ
var m map[netip.Addr]string // OK
m[netip.MustParseAddr("192.168.1.1")] = "Gateway"


Меньший расход памяти:
// net.IP - неэффективно
ips := make([]net.IP, 1000)
for i := 0; i < 1000; i++ {
ips[i] = net.ParseIP("192.168.1.1")
}
// Высокое потребление памяти из-за срезов

// netip.Addr - эффективно
addrs := make([]netip.Addr, 1000)
for i := 0; i < 1000; i++ {
addrs[i] = netip.MustParseAddr("192.168.1.1")
}
// Компактное хранение


Удобный API:
addr := netip.MustParseAddr("192.168.1.1")

// Методы с хорошим интерфейсом
addr.Is4() // true
addr.Is6() // false
addr.IsPrivate() // true
addr.IsLoopback() // false
addr.IsUnspecified() // false
addr.IsMulticast() // false
addr.Unmap() // Для IPv4-mapped IPv6
addr.String() // "192.168.1.1"

// Работа с префиксами
prefix := netip.MustParseAddrPrefix("192.168.1.0/24")
prefix.Contains(addr) // true


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
5👏1
Можно ли передавать канал в функцию как аргумент

Да, канал можно передавать в функцию как аргумент.

При этом можно ограничить направление канала:
// Только для отправки
func send(ch chan<- int) {
ch <- 42
}

// Только для чтения
func receive(ch <-chan int) {
val := <-ch
}

// Двунаправленный
func process(ch chan int) {
ch <- 1
val := <-ch
}


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

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🎉1
Можно ли через //go:linkname получить доступ к приватной функции стандартной библиотеки

Да, эта директива позволяет связать локальное имя с любым символом в рантайме, включая неэкспортируемые функции. Например, так можно вызвать приватную функцию runtime.nanotime:
package main

import _ "unsafe"

//go:linkname nanotime runtime.nanotime
func nanotime() int64

func main() {
println(nanotime())
}


Но использовать это в продакшене не стоит. Приватные функции — это деталь реализации. Они могут измениться или исчезнуть в следующей версии Go без предупреждения.

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍42
Какие у GOOS могут быть значения

Узнать список значений:
go tool dist list


Команда выведет все комбинации GOOS/GOARCH, которые поддерживает ваша версия Go.

Пример:
aix/ppc64
android/386
android/amd64
android/arm
android/arm64
darwin/amd64
darwin/arm64
dragonfly/amd64
freebsd/386
freebsd/amd64
freebsd/arm
freebsd/arm64
freebsd/riscv64
illumos/amd64
ios/amd64
ios/arm64
js/wasm
linux/386
linux/amd64
linux/arm
linux/arm64
linux/loong64
linux/mips
linux/mips64
linux/mips64le
linux/mipsle
linux/ppc64
linux/ppc64le
linux/riscv64
linux/s390x
netbsd/386
netbsd/amd64
netbsd/arm
netbsd/arm64
openbsd/386
openbsd/amd64
openbsd/arm
openbsd/arm64
openbsd/ppc64
openbsd/riscv64
plan9/386
plan9/amd64
plan9/arm
solaris/amd64
wasip1/wasm
windows/386
windows/amd64
windows/arm64


🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

🐸Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👾1
Какие виды релизов вы знаете

По стабильности:

Alpha — ранняя версия, функциональность не заморожена, баги ожидаемы. Для внутреннего тестирования.

Beta — фичи готовы, но могут быть проблемы. Уже можно показывать внешним тестировщикам.

Release Candidateкандидат в релиз. Если критичных багов не найдут, станет финальной версией.

Stable / General Availability — готов к продакшену.

По масштабу изменений:

• Major — ломающие изменения, несовместимость с предыдущей версией. 2.0.0 → 3.0.0.

• Minor — новая функциональность с обратной совместимостью. 2.1.0 → 2.2.0

• Patch — багфиксы без изменения API. 2.1.1 → 2.1.2

По способу деплоя:

• Canary — выкатка на небольшой процент пользователей

• Blue-green — две идентичные среды, переключение трафика между ними

• Rolling release — постепенное обновление без конкретных версий

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

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

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

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

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

Допустим, у вас есть структура со счётчиками, которые обновляют разные горутины:
type Counters struct {
a int64
b int64
c int64
}


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

Проблема в том, как устроен кеш процессора. CPU не читает отдельные переменные — он загружает данные кеш-линиями по 64 байта. Все три поля структуры попадают в одну линию.

Когда горутина на одном ядре изменяет поле a, процессор инвалидирует эту кеш-линию на всех остальных ядрах. Другое ядро хочет изменить b — ему приходится заново загружать линию из памяти. И так по кругу.

Это и есть Cache Contention, или false sharing — ядра конкурируют за кеш-линию, хотя работают с разными данными.

🎁 Новогодняя акция: 3 курса по цене 1
🤝
Помощь с выбором курса

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