TGViewer
Channel Public Channel
Библиотека Go для собеса | вопросы с собеседований

Библиотека Go для собеса | вопросы с собеседований

@go_interview_lib

Вопросы с собеседований по Go и ответы на них.

Учиться у нас: clc.to/iEeaZw

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

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

Наши каналы: https://t.me/proglibrary/9197
Subscribers
7.47K
Photos
286
Videos
12
Links
874

Showing posts older than #1469 · Back to latest

Older Posts 20 shown
Post #1468 1.38K
Что такое руны в Go

Руна (тип rune) — это один символ Unicode. По сути это синоним типа int32: под капотом руна хранит числовой код символа (так называемый code point).

Зачем это нужно: в Go строки хранятся в кодировке UTF-8, где один символ может занимать от 1 до 4 байт. Поэтому индексация строки по байтам (s[i]) вернёт именно байт, а не символ — и для не-ASCII текста это будут «половинки» символа.

Руны решают эту проблему: когда вы перебираете строку через range или преобразуете её в []rune, Go корректно разбивает её на цельные символы, а не на байты.

s := "Привет"
fmt.Println(len(s)) // 12 — байты
fmt.Println(len([]rune(s))) // 6 — символы

for i, r := range s {
fmt.Printf("%d: %c\n", i, r) // r имеет тип rune
}


🐸 Библиотека Go для собеса
  • 👍 9
Post #1467 1.35K
Как в Lock-Free алгоритмах борются с бесконечными повторными попытками

Когда несколько потоков одновременно «крутят» CAS, часть из них может подолгу проваливать попытки и впустую жечь процессор. Чтобы этого избежать, применяют несколько приёмов:

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

Адаптивные алгоритмы. Поведение потоков подстраивается под метрики системы — уровень контеншена, загрузку процессора — и стратегия ожидания меняется на лету.

Ограничение по времени/попыткам (timed wait). Если CAS не удаётся за отведённое число попыток или время, поток прекращает спин и переходит на fallback-путь.

Гибридный подход (hybrid locking). В качестве резерва подключаются мьютексы или другие блокирующие примитивы, когда неблокирующий путь себя не оправдывает.

Итог: цель всех этих механизмов — превратить «бесконечный спин» в контролируемое ожидание и не дать потокам молотить процессор вхолостую.

🐸 Библиотека Go для собеса
  • ❤ 5
  • 👍 2
Post #1466 798

Forwarded from Proglib.academy | IT-курсы

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

Для человека это естественная часть работы. У Claude Code этого контекста по умолчанию нет — только задача и инструкции, которые ему дали.

Поэтому в большой команде недостаточно просто выбрать хорошую модель.

❗️ Нужно ещё объяснить ей, как у вас устроена разработка: какие подходы приняты, что обязательно проверять и по каким правилам принимать решения.


🗓 23 июля в 19:00 МСК поговорим об этом на бесплатном вебинаре с Алексеем Жиряковым — он Executive Director в Сбере, руководит
GenAI Data Platform, и с этой проблемой сталкивался не раз 🔥

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

🔗 Занять место на вебинаре

🏃‍♀️ Proglib Academy
Post #1465 1.35K
Что такое трэшинг в контексте кэширования

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

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

Чаще всего трэшинг возникает, когда объём «горячих» данных превышает размер кэша или когда стратегия вытеснения плохо подходит под характер нагрузки.

🐸 Библиотека Go для собеса
  • 👍 2
Post #1463 1.47K
Чем отличаются Lock-Free и Wait-Free алгоритмы

Оба подхода относятся к неблокирующей синхронизации, но дают разные гарантии прогресса.
Lock-Free

• Гарантируют, что хотя бы один поток завершит операцию за конечное число шагов.

• Отдельные потоки при этом могут надолго застревать в повторных попытках (starvation).

• Проще в реализации и обычно показывают высокую производительность.

Wait-Free

• Гарантируют, что каждый поток завершит операцию за конечное число шагов.

• Сложнее в реализации и часто медленнее из-за более тяжёлой координации между потоками.

• Применяются там, где критично равноправие (fairness) — например, в системах реального времени.

Коротко: Lock-Free гарантирует прогресс системы в целом, а Wait-Free — прогресс каждого отдельного потока.

🐸 Библиотека Go для собеса
  • ❤ 5
Post #1462 1.41K
Как отличить закрытый канал от нулевого значения

Значение само по себе ничего не говорит. Если по каналу chan int пришёл 0, это может быть и реально отправленный ноль, и нулевое значение типа после закрытия. Поэтому в Go для приёма есть вторая переменная.

v, ok := <-ch
if !ok {
// канал закрыт и полностью вычитан
return
}
fmt.Println(v)


ok равен false только тогда, когда канал закрыт и в буфере ничего не осталось. Пока в буфере есть данные, приём из закрытого канала возвращает их с ok == true. То есть закрытие не отбрасывает уже отправленные значения.

🐸 Библиотека Go для собеса
  • ❤ 2
Post #1461 966

Forwarded from Proglib.academy | IT-курсы

🧑‍💻 Учиться агентной разработке — у тех, кто уже внедряет её в бигтехе

Курс «ИИ для разработчиков» ведут практики из ведущих российских IT-компаний 🔥

🔵 Они прошли путь от первых экспериментов с AI до рабочих процессов, в которых агенты помогают команде писать код, готовить PR и быстрее доводить задачи до продакшена.

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

🏃‍♀️ Proglib Academy
Post #1460 1.28K
🤷‍♂️ Что важнее в хорошем курсе: программа или люди, которые её создают?

У Proglib Academy вышел пост о том, на каком опыте построен новый курс по AI для разработчиков 🦴
Post #1459 1.49K
Что такое Compare-And-Swap (CAS)?

CAS — это атомарная операция, лежащая в основе многих lock-free алгоритмов. Она позволяет синхронизировать доступ к общим данным без блокировок.

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

Схематично CAS работает с тремя аргументами:
• адрес переменной,
• ожидаемое значение,
• новое значение.

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

🐸 Библиотека Go для собеса
  • 👍 3
Post #1458 1.39K
Как ограничить количество одновременных запросов к внешнему API. Какой примитив вы возьмёте и почему

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

Concurrency limit — сколько запросов летит одновременно (не больше 10 в моменте). Примитив — семафор.
Rate limit — сколько запросов в единицу времени (100 rps). Примитив — token bucket, x/time/rate.

Их часто путают. «Не больше 10 параллельных» — первое. «Не больше 100 в секунду» — второе. Дальше про concurrency.

Хороший выбор — семафор. В Go проще всего сделать его на буферизированном канале: канал ёмкости N — это счётчик свободных слотов:
sem := make(chan struct{}, 10)

for _, req := range requests {
sem <- struct{}{} // заняли слот
go func(r Request) {
defer func() { <-sem }() // освободили
callExternalAPI(r)
}(req)
}


struct{} — потому что нужен только факт занятости, он весит 0 байт. Канал даёт и счётчик, и блокировку сразу.

На практике берут errgroup.SetLimit — тот же семафор, но с ошибками, Wait и отменой контекста из коробки:
g, ctx := errgroup.WithContext(ctx)
g.SetLimit(10)

for _, req := range requests {
req := req
g.Go(func() error {
return callExternalAPI(ctx, req)
})
}
return g.Wait()


🐸 Библиотека Go для собеса
  • 👍 11
Post #1457 984

Forwarded from Proglib.academy | IT-курсы

🫡 Один и тот же запрос к AI можно выполнить двумя способами — и получить совершенно разный результат.

1️⃣ способ — просто попросить написать код. Модель может сгенерировать рабочее решение, но именно на этапе проверки часто всплывают пропущенные edge case’ы, ошибки обработки или проблемы с тестами.

2️⃣ способ — дать агенту цикл Think → Act → Observe. Он не останавливается после первой попытки: планирует действия, проверяет результат и, если находит ошибку, исправляет её и пробует снова.

Самое интересное, что разница здесь не столько в модели ❕ Claude, GPT или другая LLM могут быть одинаковыми. Разницу создаёт инженерная система вокруг них.

📅 Именно это разберём 23 июля в 19:00 (МСК) на бесплатном вебинаре с Алексеем Жиряковым (Executive Director в Сбере, GenAI Data Platform, ex-CTO Stream и KION).

На живом демо покажем, как один и тот же запрос работает без агентной системы и с ней 🔥

🔗 Регистрация

🏃‍♀️ Proglib Academy
Post #1456 1.29K
Как спроектировать пул воркеров для обработки задач из очереди. Сколько горутин запускать и от чего зависит это число

Базовая конструкция — один канал jobs как очередь и N воркеров, которые из него читают. Канал сам работает балансировщиком: свободный воркер забирает следующую задачу, вручную раздавать ничего не нужно. Для управления жизненным циклом добавляем context (отмена, таймаут, shutdown), sync.WaitGroup (дождаться завершения всех) и правило «кто пишет в канал, тот его и закрывает» — results закрываем только после wg.Wait(), иначе паника. Закрытие jobs — сигнал воркерам, что задачи кончились.

Сколько горутин — зависит от природы задачи. Для CPU-bound (вычисления, парсинг) смысла запускать больше горутин, чем ядер, нет: они будут драться за те же ядра и добавлять оверхед на переключение контекста. Ориентир — runtime.GOMAXPROCS(0). Для IO-bound (БД, HTTP, диск) горутина большую часть времени спит в ожидании ответа, поэтому воркеров имеет смысл сильно больше ядер — десятки, сотни. Но потолок здесь задаёт не CPU, а узкое место вниз по потоку: пул коннектов к БД, rate limit API, лимит дескрипторов. Запускать 500 воркеров при 20 коннектах к базе бессмысленно.

Грубая прикидка через закон Литтла: N ≈ ядра × (1 + время_ожидания / время_CPU). Плюс не забываем про память — горутина дешёвая (~2–8 КБ стека), но при сотнях тысяч воркеров плюс их буферы это уже гигабайты.

Правильный инженерный ответ: точное число не угадывается, а подбирается. Берём разумный старт (GOMAXPROCS для CPU, кратно больше для IO), вешаем метрики (p99-латентность, throughput, глубина очереди, загрузка CPU) и тюним под реальную нагрузку. Число воркеров — это параметр конфигурации, а не константа в коде. И отдельно важен backpressure: если продьюсер быстрее пула, нужно заранее решить — копить в буфере, блокировать продьюсера или дропать задачи, иначе очередь растёт до OOM.

🐸 Библиотека Go для собеса
  • 👍 4
  • ❤ 3
Post #1455 1.07K
🔥 Курс «Разработка ИИ-агентов» стартовал, но вы еще успеваете присоединиться!

Мы только начали, а первый практический воркшоп пройдет только 23 июля. До этого времени вы спокойно успеете изучить материалы и нагнать группу.

💼 Главная фишка: финальный проект в портфолио:

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


🎁 Упомяните менеджеру специальное предложение «3 курса по цене 1»: Берете VIP-тариф — получаете курс «Разработка ИИ-агентов», хардкорный «AgentOps» и ещё один курс на выбор. Выгода 129.000 ₽!

Двери потока вот-вот закроются окончательно. Успейте забрать стек курсов и начать работу над реальным проектом

🔗 Занять место и забрать 3 курса
  • 😢 1
Post #1454 1.09K
Как предотвратить XSS и SQL инъекции

Мы никогда не склеиваем запрос строкой. Всегда плейсхолдеры драйвера, значения уходят отдельно от текста запроса:
row := db.QueryRowContext(ctx, "SELECT id FROM users WHERE email = $1", email)


Имена таблиц и колонок так подставить нельзя, для них белый список допустимых значений:
var allowed = map[string]string{"created": "created_at", "email": "email"}
col, ok := allowed[r.URL.Query().Get("sort")]
if !ok {
col = "created_at"
}
query := fmt.Sprintf("SELECT id FROM users ORDER BY %s DESC", col)


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

XSS

Пользовательский текст не попадает в HTML напрямую. Рендерим через html/template, он экранирует с учётом контекста, то есть по разному внутри тега, атрибута, href и блока <script>. text/template не экранирует ничего, в веб хендлере его быть не должно.
Приводить ввод к template.HTML нельзя, это отключение защиты. Если пользователю нужна разметка, чистим санитайзером вроде bluemonday по белому списку тегов.

Для API хватает encoding/json, но заголовки обязательны, иначе браузер угадает тип и отрендерит ответ как страницу:
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Header().Set("X-Content-Type-Options", "nosniff")


Сверху Content-Security-Policy и куки с HttpOnly, чтобы случайная дыра не привела к краже сессии.

🐸 Библиотека Go для собеса
  • ❤ 2
Post #1453 1.09K
🔥 Стартуем СЕГОДНЯ! Новый поток курса «Разработка ИИ-агентов» открыт

По этому поводу мы решили выложить закрытую запись одного из уроков из программы. Найти её в поиске YouTube нельзя — она доступна только по ссылке и всем, кто будет на курсе.

Внутри глубокий разбор LLM от Алексея Яндутова (Senior ML-инженер, развивал ответы «Алисы» и «Нейро» в Яндексе). Учимся получать точный результат без галлюцинаций.

Что внутри урока:

- Устройство LLM.
- Рабочие шаблоны промптов (Persona, Chain-of-Thought и др.).
- Разбор реального кейса Яндекса. Как автоматизировать разметку, обойти качество людей на 5% и срезать косты на 60%.


После просмотра вы поймете, когда хватает промпт-инжиниринга, а когда нужен RAG или fine-tuning.

👉Смотреть закрытый урок на YouTube

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

🔗 Занять место на курсе
  • ❤ 1
Post #1452 1.14K
🚀 Уже завтра стартует новый поток курса «ИИ-агенты»!

Мы собрали мощнейший состав преподавателей. Учить вас проектировать архитектуру и собирать продакшн-агентов будут инженеры и исследователи из топовых IT-компаний.

Старт уже завтра!

Сомневаетесь, подойдет ли вам программа и подача? Начните с бесплатного демо-урока!

Всего за 2 часа вы заглянете под капот ИИ-агента, поймете, чем мышление модели отличается от ее ответа, и научите систему чинить собственный код. Это идеальный способ протестировать нашу платформу перед покупкой.

🔗 Пройти демо-урок и занять место на курсе
Post #1451 1.17K
Как найти подстроку в строке

Задача звучит просто, но у неё три разных ответа. Нужно узнать, есть ли подстрока вообще. Нужно узнать, где она находится. Нужно достать то, что вокруг неё. Для каждого случая в пакете strings есть своя функция, и брать не ту это лишняя работа.

Просто проверить наличие

if strings.Contains(s, "error") {
// подстрока есть
}


strings.Contains
возвращает bool. Рядом живут strings.HasPrefix и strings.HasSuffix для начала и конца строки, они дешевле, потому что не сканируют всё подряд.

if strings.HasPrefix(path, "/api/") {
...
}


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

Найти позицию

i := strings.Index(s, "role=")
if i == -1 {
return errors.New("not found")
}


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

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

Достать содержимое

Чаще всего индекс нужен не сам по себе, а чтобы отрезать кусок. Тогда strings.Cut короче и понятнее.

before, after, found := strings.Cut("key=value", "=")
if !found {
return errors.New("bad format")
}
// before "key", after "value"


Это идиоматичный способ с Go 1.18. Он заменяет связку Index плюс два среза и не даёт ошибиться со смещением на длину разделителя.

🐸 Библиотека Go для собеса
  • ❤ 6
Post #1450 1.09K
🤨 Как заставить AI-агента не ломать архитектуру, а нормально писать код?

Мы привыкли общаться с ИИ промптами, но для автономных систем это путь к бесконечным циклам и сливу бюджета. Чтобы убрать хаос, инженеры переходят на Spec-Driven Development (SDD).

Вот как этот подход меняет работу агента на практике:

🔹Контракт вместо текста. Сначала пишется строгая спецификация (JSON-схема/OpenAPI) и автотесты. Агент зажат в рамки интерфейсов, за которые физически не может выйти.
🔹Контроль на шагах. Внутри петли Think-Act-Observe агент сверяет действия со спецификацией.
🔹Саморефлексия. Если ИИ нарушил типы или «додумал» лишнее, тест падает. Агент получает ошибку в контекст и сам правит код, не выходя за рамки ТЗ.

Это лишь база того, как укротить ИИ-разработку. Если вы хотите глубоко внедрить эту методологию, научиться проектировать архитектурные контракты и собирать отказоустойчивые системы —оставляйте заявку на наш новый курс по Spec-Driven Development. Стартуем совсем скоро🙂
  • ❤ 1
  • 😁 1
  • 😢 1
Post #1449 945
Как извлечь подстроку из строки

Строка в Go это неизменяемый срез байт. Поэтому подстрока берётся так же, как срез, но с одной оговоркой. Индексы считаются в байтах, а не в символах. На ASCII разницы не видно, на кириллице или эмодзи всё ломается.

Срез по байтам

s := "hello world"
fmt.Println(s[0:5]) // hello
fmt.Println(s[6:]) // world


Такой срез не копирует данные, он ссылается на тот же массив байт. Работает за O(1).

Теперь то же самое с кириллицей:
s := "привет"
fmt.Println(s[0:3]) // "пр"? нет, это "п" с хвостом


Каждая кириллическая буква в UTF-8 занимает два байта, так что s[0:3] разрежет символ пополам и вы получите битые данные.

Срез по символам

Если нужны именно символы, переводим строку в срез рун:
r := []rune("привет")
fmt.Println(string(r[0:3])) // при


Здесь уже есть аллокация и проход по всей строке, то есть O(n). Для длинных строк в горячем цикле это заметно.

🐸 Библиотека Go для собеса
  • ❤ 2
Older posts →
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →