Библиотека Go для собеса | вопросы с собеседований
6.87K subscribers
248 photos
9 videos
1 file
533 links
Вопросы с собеседований по Go и ответы на них.

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

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

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

Наши каналы: https://t.me/proglibrary/9197
Download Telegram
Чем отличаются методы Time.Sub() и Time.Add() в пакете time

Time.Sub() — метод вычисляет разницу между двумя моментами времени.

start := time.Now()
time.Sleep(2 * time.Second)
end := time.Now()

duration := end.Sub(start) // ≈ 2 секунды
fmt.Println(duration) // 2.001234567s


Time.Add() — метод добавляет или вычитает при отрицательном значении длительность к/от момента времени и возвращает новое время.

now := time.Now()
tomorrow := now.Add(24 * time.Hour)
yesterday := now.Add(-24 * time.Hour)

fmt.Println("Завтра:", tomorrow)
fmt.Println("Вчера:", yesterday)


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
🧠 Курс «Математика для Data Science»

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

Но главное, математика понятна, если объяснить её на языке разработки.

📘 Курс «Математика для Data Science»:

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

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

🗓️ Старт курса → 6 ноября

👉 Записаться на курс
🌚2
Почему time.After для таймаутов может привести к утечке памяти

Когда вы вызываете time.After, внутри создаётся таймер. Этот таймер будет жить и занимать память до самого срабатывания — даже если он вам больше не нужен.

Типичный код с утечкой:
for {
select {
case msg := <-messages:
process(msg)
case <-time.After(5 * time.Second):
// проверяем что-то каждые 5 секунд
}
}


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

Правильное решение

Используйте time.NewTimer — он даёт контроль над таймером:
timer := time.NewTimer(5 * time.Second)
defer timer.Stop()

for {
select {
case msg := <-messages:
process(msg)
timer.Reset(5 * time.Second)
case <-timer.C:
// проверка по таймауту
timer.Reset(5 * time.Second)
}
}


Теперь таймер один — вы его переиспользуете. После обработки сообщения сбрасываете через Reset, и он снова начинает отсчёт. Не нужно? Вызываете Stop, и память освобождается сразу.

Если таймаут разовый и вы точно знаете, что он сработает — time.After подходит:
select {
case result := <-doWork():
return result
case <-time.After(10 * time.Second):
return errors.New("timeout")
}


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

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

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥133👍3👾2😢1
This media is not supported in your browser
VIEW IN TELEGRAM
🔥Обсуждаем все, что волнует Go-сообщество: 1 ноября Яндекс проведет митап для разработчиков по Go

Помимо выступлений спикеров — нетворк и обсуждение свежих релизов, инструментов, новых подходов и архитектурных решений.

В докладной части: СТО Яндекс Игр Степан Пестерников расскажет, как они используют KV-хранилища и кеши. Старший разработчик Яндекс Маркета Александр Никитин покажет, как с помощью Debug Tree разобраться, как работает сложная многопоточная кодовая база. Разработчик бэкенда Плюса и Финтеха Игорь Панасюк разберет новый garbage collector в Go 1.25, и расскажет, какое влияние он окажет на ваши сервисы.

Отдельно на круглых столах офлайн-участники смогут обсудить использование AI-инструментов, highload, нетипичное применение Golang и другие актуальные для go-разработки темы.

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

💥 Регистрируемся здесь.
3👍1🤩1
Зачем нужна функция runtime.Version() и для чего её используют

runtime.Version() возвращает версию Go, которой скомпилирована программа.

Используется для:

• Диагностики — когда нужно понять, какой версией собран бинарник в продакшене

• Логирования — записываем версию Go при старте приложения для отладки

• Health-check эндпоинтов — отдаём информацию о версии в /health или /version

• Условной логики — редко, но иногда нужно обойти баги конкретных версий компилятора

• Валидации окружения — проверяем, что приложение собрано требуемой версией Go

Айтишники всегда развиваются. В этом отлично помогают наши курсы. Обязательно чекните — до конца октября ряд курсов со скидкой.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👾1
🔎 Собес сам себя не пройдет

Ты готов к собеседованию? А если проверю?

Залетай к нам и забирай курсы со скидкой 40%. Только до конца октября можно узнать много нового и отточить навыки.

🎯 Забирай курсы:

🐍 python для разработчиков;
🧮 алгоритмы и структуры данных;
📝 архитектуры и шаблоны проектирования;
🧩 основы IT для новичков.

Не упусти скидку и получи долгожданный оффер!
Какая разница между var, := и new() при объявлении переменных

var используется, когда нужно объявить переменную с явным типом или без начального значения:
var count int           // инициализируется нулевым значением (0)
var name string // инициализируется "" (пустая строка)
var isActive bool // инициализируется false
var users []User // инициализируется nil

var total = 100 // тип выводится автоматически
var message string = "Hello" // явное указание типа


Оператор := — это синтаксический сахар для объявления и инициализации переменных внутри функций:
func processOrder() {
status := "pending" // эквивалентно var status string = "pending"
count := 42 // эквивалентно var count int = 42
user := getUser() // тип выводится из возвращаемого значения
}


new() выделяет память, инициализирует её нулевым значением и возвращает указатель:
ptr := new(int)         // *int, значение 0
fmt.Println(*ptr) // 0

user := new(User) // *User, все поля в нулевых значениях


На практике new() используется редко, потому что короткое объявление с & делает то же самое, но понятнее:
// Эквивалентные записи:
ptr1 := new(int)
ptr2 := &int{} // более идиоматично

user1 := new(User)
user2 := &User{} // более наглядно


🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Какой объект требуется для создания sync.Cond

Для создания sync.Cond в Go требуется любой объект, реализующий интерфейс sync.Locker, например sync.Mutex или sync.RWMutex.

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3
🎲 Знаешь, что хуже всего на собесе?

Когда задают простой вопрос, а ты не можешь ответить.

🤔 Это ощущение, когда понимаешь:
«Блин, я это знаю... вроде... сейчас...»


От «я знаю...» до «сейчас объясню!» всего один курс.

Алгоритмы и структуры данных — от Big O до задач криптографии.

Python для разработчиков — пиши чистый и эффективный код.

Архитектуры и шаблоны — строй системы, которые масштабируются.

Основы IT — всё необходимое для входа в профессию.

Выбирай любой и забирай со скидкой 40% только до конца октября.

🔗 Выбрать курс
Что такое неэкспортируемая пустая структура

Это структура, определённая как struct{}, без полей и с именем, начинающимся со строчной буквы, чтобы ограничить область видимости внутри пакета.

Зачем она нужна

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

• Так как struct{} занимает 0 байт, её используют в ситуациях, где нужно просто присутствие элемента без данных:
set := map[string]struct{}{}
set["apple"] = struct{}{}


• Пустая структура идеальна для каналов, передающих только сигнал, а не данные:
done := make(chan struct{})
go func() {
// работа
done <- struct{}{}
}()
<-done


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

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

Стандартная библиотекаmath.Round(), math.Floor(), math.Ceil() и math.Trunc()
math.Round(2.5)  // 3
math.Round(2.4) // 2
math.Round(-2.5) // -3
math.Floor(2.7) // 2 — всегда вниз
math.Ceil(2.1) // 3 — всегда вверх
math.Trunc(2.9) // 2
math.Trunc(-2.9) // -2


Важный нюанс: эти функции возвращают float64. Если нужно целое число, приводим к int:
result := int(math.Round(2.5)) // 3


Округление до N знаков после запятой вручную:
func roundToDecimal(num float64, precision int) float64 {
shift := math.Pow(10, float64(precision))
return math.Round(num * shift) / shift
}

roundToDecimal(3.14159, 2) // 3.14


Но здесь есть подвох с float64 — погрешность может накапливаться. Для финансов это не подходит.

Decimal библиотеки:
import "github.com/shopspring/decimal"

num := decimal.NewFromFloat(3.14159)

num.Round(2) // 3.14
num.RoundUp(2) // 3.15 — всегда вверх
num.RoundDown(2) // 3.14 — всегда вниз
num.RoundBank(2) // банковское округление


math/big для высокой точности:
num := new(big.Float).SetFloat64(3.14159)
rounded := new(big.Float)

// Устанавливаем точность и режим округления
rounded.SetPrec(53) // точность в битах
num.SetMode(big.ToNearestEven) // режим округления


Для финансов всегда decimal с явным режимом округления. Для остального — math вполне достаточен.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
👍5👾1
Что такое жадный алгоритм

Жадный алгоритм — это когда мы принимаем решение, которое кажется лучшим прямо сейчас, не думая о последствиях в будущем. Никогда не возвращаемся назад и не пересматриваем выбор.

Пример. Задача о размене монет:
// Выдать сдачу 63 рубля монетами: 50, 10, 5, 2, 1
// Жадный подход: берем максимальную монету
func giveChange(amount int) []int {
coins := []int{50, 10, 5, 2, 1}
result := []int{}

for _, coin := range coins {
for amount >= coin {
result = append(result, coin)
amount -= coin
}
}
return result // [50, 10, 2, 1] - работает!
}


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

Закрой все вкладки со словами «MacBook», «купить ноутбук», «ноут в рассрочку». Потому что у нас есть решение лучше.

🔥 Proglib разыгрывает MacBook Pro 14. Формула простая: покупаешь любой курс до 15 ноября → учишься 2 недели → пишешь куратору #розыгрыш

Пока у тебя открыто 147 вкладок с ценами, кто-то уже прокачивает скилы и может забрать приз.

👉🏻 Выбрать курс для участия
🥱5
Как переобъявить переменные

В Go нельзя полностью переобъявить переменную с тем же именем в одной области видимости — это вызовет ошибку компиляции.

Внутри функции можно использовать оператор :=, если одновременно присутствует новая переменная. Пример:
a := 1       // a объявлена
a, b := 2, 3 // a присваивается новое значение, а b объявляется


Можно объявить переменную с одинаковым именем в разных областях видимости:
var a = 1
func test() {
var a = 2 // это другая переменная, локальная для функции
}


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

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

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

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥94👍2🥱1
Как работает atomic.Value

atomic.Value используется для безопасного хранения и чтения значения из разных горутин без использования явных блокировок.

Для записи используется метод Store, для чтения — Load. Хранящееся значение должно быть одного типа на протяжении всего времени жизни экземпляра atomic.Value, иначе при попытке сохранить значение другого типа возникнет паника.

atomic.Value синхронизирует само значение, но не вложенные поля, если сохраняется, например, структура с внутренними pointer-полями.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
1
⚡️ Механизм запущен, часики тикают

Прямо сейчас кто-то уже купил курс со скидкой 40%, открыл первый урок и уже на пути к MacBook Pro 14.

А ты всё ещё читаешь этот пост...

Дедлайны не ждут:

31 октября — скидка 40% сгорает
15 ноября — розыгрыш MacBook

🎯 Правила участия:

→ купить любой курс до 31 октября
→ отучиться 2 недели
→ написать #розыгрыш куратору

🕊️ Не упусти свой шанс
Что происходит с горутиной, если контекст, переданный в неё, отменён с помощью cancel

Если контекст, переданный горутине, отменён с помощью функции cancel(), в горутине должен быть предусмотрен код, который регулярно проверяет состояние контекста, обычно через <-ctx.Done().

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

Сам по себе вызов cancel() не останавливает горутину. Он лишь посылает сигнал отмены, который надо обрабатывать в коде.

🐸 Библиотека Go для собеса
Please open Telegram to view this post
VIEW IN TELEGRAM
6
Go как ядро сложной dev-платформы? Да, и это SourceCraft! 🤯

Интересный факт для Go-комьюнити: ядром git-сервера SourceCraft стал переработанный Go-движок go-git. Команда Яндекса перенесла слой хранения в облако (Object Storage + PostgreSQL), добившись масштабируемости. И почти вся остальная бэкенд-обвязка платформы тоже написана на Go!

Получился редкий пример, где Go — не просто один из языков, а основа сложной инфраструктуры. Разработчики платформы говорят, что это даёт масштабирование без потери быстродействия. Можно залить крупный проект и проверить, как он грузится. 🤔
👍31🔥1
В чем отличие полей-структур и полей интерфейсов

Поля-структуры содержат конкретную реализацию данных и методов. Когда вы встраиваете структуру в другую структуру (embedding), вы получаете доступ к её полям и методам напрямую, и эти методы уже реализованы.

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

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

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