golangtests | Unsorted

Telegram-канал golangtests - Go tests

7530

По всем вопросам- @haarrp @itchannels_telegram - 🔥полезные ит-каналы https://t.me/Golang_google - Golang программирование @golangl - golang chat @GolangJobsit - golang channel jobs @golang_jobsgo - go chat jobs

Subscribe to a channel

Go tests

Nil-интерфейс в Go: почему err == nil выдаёт false?


Nil-интерфейс в Go ломает даже опытных разработчиков: функция возвращает nil-указатель *E, а проверка err == nil всё равно даёт false. Причина в том, что интерфейс хранит пару из типа и значения, и пока тип *E на месте, интерфейс не считается пустым. Хочешь вернуть «нет ошибки», возвращай nil явно.

youtube.com/shorts/6LK-o-BSjHA?feature=share

Читать полностью…

Go tests

Не застревайте в прошлом — учитесь новым навыкам и ИИ

Чтобы успевать за требованиями рынка, освойте новую профессию и нейросети в Практикуме. До 30 сентября действует скидка 16% на все курсы. 

Выбрать курс

Как всё устроено: 

— нейросети уже в каждом курсе: учим профессиям сразу с ИИ, чтобы ваше резюме было заметнее, а трудоустройство — увереннее;

— эксперты — практики, которые двигают ИИ-индустрию: перенимайте опыт у профи из Яндекса, Сбера, Т-Банка и других бигтех-компаний;

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

Начните учиться бесплатно и получите скидку 16% — она автоматически появится в личном кабинете. 

Учиться!

Erid: 2SDnjeMs7zT
Название: ООО "ЯНДЕКС"
ИНН: 7736207543

Читать полностью…

Go tests

🔥 Хочешь расти в IT быстрее остальных? Перестань учиться в одиночку

Можно годами смотреть курсы, читать документацию и всё равно топтаться на месте.

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

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

AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: /channel/+90Z5TAyfuNU5YmRi
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_ci
Java: t.me/javatg
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: /channel/gamedev
Haskell: t.me/haskell_tg

Собеседования и карьера:

DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview

Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: /channel/addlist/2Ls-snqEeytkMDgy
Папка Frontend: /channel/addlist/mzMMG3RPZhY2M2Iy

Полезное сверху:

ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: /channel/+rKBQEMccAA01MTcy
ИТ-книги бесплатно: /channel/addlist/BkskQciUW_FhNjEy

Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg

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

Читать полностью…

Go tests

Go-задача: что выведет этот код?


package main

import "fmt"

func main() {
var funcs []func()

for i := range 3 {
funcs = append(funcs, func() {
fmt.Println(i)
})
}

for _, f := range funcs {
f()
}
}


Что будет в выводе?


A)

0
0
0

😎

2
2
2

C)

0
1
2

D) Код не скомпилируется


Правильный ответ: C — 0, 1, 2

Почему?

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

Плюс range теперь можно использовать прямо по integer:

```go
for i := range 3
```

Это даёт значения:

```go
0
1
2
```

Поэтому каждое замыкание запоминает своё i.

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

```go
i := i
```
внутри цикла.

Хороший вопрос на собеседовании:

Почему этот код сегодня выводит 0, 1, 2, хотя раньше похожий пример мог вести себя иначе?

Читать полностью…

Go tests

Лето, ИТ-Пикник и музыка известных артистов уже через несколько дней!

8 августа в Коломенском пройдет ИТ-Пикник.

В программе — выступления проекта LAB Антона Беляева, IOWA, Cream Soda, Pompeya, мартина и Совы.

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

Зарегистрироваться и узнать подробности можно на сайте мероприятия.

В билет входит +1 — можно позвать близких и друзей.

До встречи в месте притяжения ИТ.

Читать полностью…

Go tests

Каждый год в середине лета мы с друзьями собираемся на E-CODE. Ещё относительно молодая конфа Ozon Tech стала уже своего рода легендой. Не удивительно: хардовость официальной части здесь не уступает громкости афтерпати.

На E-CODE 2026 нас по части бэкэнда ждут:

• Runtime Async с его + и –
• трассировка с eBPF
• ускорение на SIMD
• построение кастомной real-time системы видеоаналитики
• сравнительный анализ алгоритмов сборки мусора

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

Регистрируйтесь сейчас, чтобы услышать это всё вживую: https://ecode.ozon.tech/

12 и 13 сентября, Москва. До встречи на E-CODE!

Читать полностью…

Go tests

🔥 Хочешь быстрее расти в IT? Хватит учиться в одиночку

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

Окружение решает больше, чем кажется.

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

AI: t.me/ai_machinelearning_big_data
Python: t.me/pythonl
Linux: t.me/linuxacademiya
Хакинг: t.me/linuxkalii
DevOps: t.me/DevOPSitsec
Docker: t.me/DevopsDocker
Golang: t.me/Golang_google
Rust: t.me/rust_code
C++: t.me/cpluspluc
C#: t.me/csharp_1001_notes
Java: t.me/java_library
JavaScript: t.me/javascriptv
React: t.me/react_tg
Frontend: t.me/front
PHP: t.me/phpshka
Android: t.me/android_its
Мобильная разработка: t.me/mobdevelop
Базы данных: t.me/sqlhub
Data Science: t.me/data_analysis_ml
Big Data: t.me/bigdatai
Математика: t.me/data_math
Физика: t.me/fizmat
Kubernetes: t.me/kubernetc
GameDev: /channel/gamedev
Haskell: t.me/haskell_tg

Собеседования и карьера:

DS собеседования: t.me/machinelearning_interview
Python собеседования: t.me/python_job_interview

Папка с вакансиями: t.me/addlist/_zyy_jQ_QUsyM2Vi
Папка Go разработчика: t.me/addlist/MUtJEeJSxeY2YTFi
Папка Python разработчика: t.me/addlist/eEPya-HF6mkxMGIy
Папка ML: /channel/addlist/2Ls-snqEeytkMDgy
Папка Frontend: /channel/addlist/mzMMG3RPZhY2M2Iy

Полезное сверху:

ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: @courses
ИТ-книги бесплатно: /channel/addlist/BkskQciUW_FhNjEy

Max Ai: https://max.ru/ai_machinelearning_big_data
Max python: https://max.ru/pythonl
ТЕХНО: https://max.ru/vistehno
Max Go: https://max.ru/Golang_google
Max Linux: https://max.ru/linuxkalii
Devops: https://max.ru/DevOPSitsec
C#: https://max.ru/csharp_ci
C++: https://max.ru/cpluspluc
SQL: https://max.ru/sqlhub
Java: https://max.ru/javatg

Подписывайся на нужные направления и собирай себе ленту, которая реально двигает вперёд.

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

Читать полностью…

Go tests

👣 Golang-задача с подвохом

Версия: Go 1.23+

Что выведет код?


package main

import "fmt"

func numbers(yield func(int) bool) {
defer fmt.Println("iterator: defer")

for i := 0; i < 5; i++ {
if !yield(i) {
fmt.Println("iterator: stopped")
return
}

fmt.Println("iterator: after yield", i)
}
}

func main() {
for n := range numbers {
fmt.Println("main:", n)

if n == 2 {
break
}
}

fmt.Println("main: done")
}


Многие ждут, что после break итератор просто мгновенно исчезнет.

Но в Go 1.23 появился range по функции.

Под капотом yield возвращает false, если внешний цикл остановился через break.

Ответ:

```txt id="5glpxa"
main: 0
iterator: after yield 0
main: 1
iterator: after yield 1
main: 2
iterator: stopped
iterator: defer
main: done
```

Подвох в том, что `break` происходит во внешнем цикле, но функция-итератор получает сигнал остановки через `yield`.

Если не проверить `!yield(i)`, можно продолжить работу после того, как потребитель уже вышел из цикла.

Читать полностью…

Go tests

⚡️ Вышло большое обновление популярного курса- Ai AI агенты, которые реально работают в проде!

Вы всё ещё пишете обёртки над ChatGPT и называете это «AI-продуктом»?

Пока вы промптите - рынок переходит на агентные системы. Те, что принимают решения, ходят в API, работают с Postgres и Redis, управляют браузером через Playwright.

И 90% таких систем ломаются между ноутбуком и продом.

AI Agents Engineering - курс, который закрывает этот разрыв. LangGraph, AutoGen, Computer Use, LLMOps. 8 модулей, 120+ шагов - от архитектуры до деплоя в Docker.

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

👉 48 часов действует скидка на курс 55 процентов: https://stepik.org/a/276971/

Читать полностью…

Go tests

Проект можно запустить быстро, но выдержит ли он рост нагрузки, требования к безопасности и отказоустойчивости? Часто на старте думают только о функциях. Производительность, масштабирование, защита — добавим потом. В реальности это «потом» оборачивается дорогими переделками и компромиссами.

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

Спикер Александр Хохлов — архитектор платформенных решений в ГК Иннотех.

Открытый урок проходит в преддверии старта курса «Проектирование систем».

Регистрируйтесь сейчас - напомним перед вебинаром: регистрация

Реклама. ООО "ОТУС ОНЛАЙН-ОБРАЗОВАНИЕ". ИНН 9705100963.

Читать полностью…

Go tests

❓ Почему код падает и как это исправить

Функция должна заполнить срез и мапу,
но сейчас она падает с panic.

В чём проблема?


func fillData(s []int, m map[string]int) {
// Добавляем в срез
s = append(s, 10, 20, 30)

// Добавляем в мапу
m["count"] = len(s)
m["total"] = 60

fmt.Println("Срез:", s)
fmt.Println("Мапа:", m)
}

func main() {
fillData(nil, nil)
}


💡 Подсказка: срез и мапа ведут себя по-разному

append к nil срезу работает нормально
запись в nil map → panic

🔥 В чём ошибка

m не инициализирована → это nil map
в неё нельзя записывать значения

Читать полностью…

Go tests

Хитрая Go-задача:


package main

import "fmt"

type uint128 struct {
Hi uint64
Lo uint64
}

func f(φ uint128, β int) uint32 {
return uint32(φ.Hi >> (63 - β))
}

func main() {
x := uint128{Hi: 0x8000000000000001}

fmt.Println(f(x, 0))
fmt.Println(f(x, 1))
fmt.Println(f(x, 63))
}


Вопросы:

Что выведет код?
Что будет при β = 64?
Можно ли объявить одновременно beta и β?

Ожидаемый ответ:

1
2
1

Подвох:

сдвиг зависит от β
возможен отрицательный shift
обрезание до uint32
beta и β - разные переменные


• Вам нужно понять, как работает сдвиг вправо
заметить, что в конце результат режется до uint32

• увидеть, что при β = 64 получится отрицательный сдвиг:

63 - 64 = -1
и ещё понять, что beta и β в Go - это разные имена переменных

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


Запустить код: https://go.dev/play/

Полезные ресурсы Go 🚀Max

@golangtests

Читать полностью…

Go tests

👣 Большинство изучают Go ради синтаксиса.

Ты научишься писать сервисы, которые работают в продакшене.

Это не про «Hello, World» и горутины ради галочки.
Это про бэкенд на Go, который:

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

Ты начнёшь видеть Go не как язык, а как инструмент для построения систем.

В итоге ты сможешь:

* писать высоконагруженные API
* создавать микросервисы
* работать с базами данных и очередями
* разбираться в конкурентности и производительности
* брать коммерческие backend-проекты

Это навык, который ценится на рынке.
Не «знаю Go», а умею делать быстрые и надёжные сервисы.

🎁 48 часов скидка 50% на Stepik: https://stepik.org/a/274119/

Читать полностью…

Go tests

🔥 PrimeView - реальная производительность языков без маркетинга

https://plummerssoftwarellc.github.io/PrimeView/report

PrimeView - это живой бенчмарк, который сравнивает языки программирования на одной задаче: генерация простых чисел.

Без синтетических тестов.
Без “идеальных условий”.
Только:

* один алгоритм
* одинаковые правила
* реальные оптимизации от разработчиков

Что показывают результаты:

* C и C++ стабильно в лидерах
* Rust и Zig уверенно конкурируют с нативным кодом
* Go показывает сильные результаты при грамотной оптимизации
* разница между реализациями внутри одного языка часто больше, чем между языками

Ключевой инсайт:

Производительность определяет не язык.
Производительность определяет инженер.

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

plummerssoftwarellc.github.io/PrimeView/report

Читать полностью…

Go tests

Это один из самых любимых вопросов на Go-собеседованиях.
Проверяют, понимаешь ли ты, как устроены slice, len / cap и что реально делает append.

Что выведет программа?


package main

import "fmt"

func add(s []int) {
s = append(s, 99)
}

func main() {
a := make([]int, 2, 4)
a[0], a[1] = 1, 2

add(a)

fmt.Println("a:", a)
fmt.Println("a[:3]:", a[:3])
}


Разбор

```go
a := make([]int, 2, 4)
len = 2
cap = 4
underlying array = [1, 2, _, _]
```

Слайс - это структура:
```go
pointer -> array
len
cap
```

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

Внутри:
```go
s = append(s, 99)
```

Так как cap=4, места хватает → новый массив НЕ создаётся.
В память записывается:

```go
[1, 2, 99, _]
```

Но:

s внутри функции: len=3

```go
a в main: len=2
```

Вывод
```go
a: [1 2]
a[:3]: [1 2 99]
```

Вопрос 2 (сложнее)
package main



import "fmt"

func add(s []int) {
s = append(s, 99)
s[0] = 42
}

func main() {
a := []int{1, 2}
add(a)

fmt.Println("a:", a)
}


Разбор
```go
a := []int{1,2}
len=2
cap=2
```

Теперь в append места нет → создаётся новый массив.

Внутри add:
```go
new array = [1 2 99]
s -> указывает на новый массив
```

Но a всё ещё указывает на старый:

```go
old array = [1 2]
```

Строка:

```go
s[0] = 42
```

Меняет новый массив, не старый.

Вывод
```go
a: [1 2]
```

Главная идея

Поведение append зависит от capacity.

Условие Что происходит
cap хватает меняется тот же массив
cap не хватает создаётся новый

Slice передаётся по значению, но содержит указатель на массив.
append может незаметно "оторвать" его от исходных данных.

Как писать безопасно
```go
func add(s []int) []int {
s = append(s, 99)
return s
}

a = add(a)
```

Что этим проверяют на собесе

• slice ≠ массив
• len vs cap
• устройство slice header
• поведение append
• aliasing памяти

Если это не понимать, будут странные баги в продакшене.


Запустить код: https://go.dev/play/p/V9KyryLj3TV

Читать полностью…

Go tests

Задача по Go: `select` и побочные эффекты

Что выведет программа?


package main

import "fmt"

func value() int {
fmt.Print("A")
return 42
}

func main() {
var ch chan int

select {
case ch <- value():
fmt.Print("B")
default:
fmt.Print("C")
}
}


Варианты:

1. C
2. AC
3. AB
4. Программа зависнет

Ответ: 2. Вывод будет `AC`.

ch равен nil, поэтому отправка никогда не может выполниться и select выбирает default.

Но перед выбором ветки Go один раз вычисляет каналы и правые части всех операций отправки. Поэтому value() всё равно вызывается и печатает A. Затем выполняется default, который печатает C.

#Golang #GoLang #Programming

Читать полностью…

Go tests

👣 Задача на Go 1.27: concurrent job scheduler с generic methods

Нужно реализовать библиотеку scheduler, которая запускает задачи параллельно, ограничивает concurrency, поддерживает context.Context, retry, timeout и возвращает типизированные результаты.

💡 Требования

Создайте generic-тип:


type Scheduler[T any] struct {
// ...
}

Он должен поддерживать регистрацию задач:

type Job[T any] func(ctx context.Context) (T, error)

И новый generic method Go 1.27:

func (s *Scheduler[T]) Map[R any](
ctx context.Context,
fn func(context.Context, T) (R, error),
) ([]R, error)
Функциональность

Scheduler должен уметь:

выполнять не более N задач одновременно;
отменять все оставшиеся задачи при отмене context.Context;
задавать timeout для каждой задачи;
делать до K retry с exponential backoff;
сохранять исходный порядок результатов;
не иметь data race;
корректно завершать goroutines без утечек;
возвращать ошибку с информацией, какая задача упала.

Пример API:

```go
s := scheduler.New[int](
scheduler.WithWorkers(8),
scheduler.WithRetries(3),
scheduler.WithTimeout(2*time.Second),
)

for i := range 100 {
n := i

s.Add(func(ctx context.Context) (int, error) {
return expensiveOperation(ctx, n)
})
}

values, err := s.Run(ctx)

strings, err := s.Map(ctx, func(
ctx context.Context,
value int,
) (string, error) {
return strconv.Itoa(value), nil
})


Ограничения

• Нельзя использовать сторонние worker-pool библиотеки.
• Можно использовать только standard library.
• Нельзя запускать goroutine на каждую задачу без ограничения.
• Нельзя игнорировать ctx.Done().

Решение должно проходить:

go test ./...
go test -race ./...
go vet ./...
Дополнительный уровень


Добавьте:


func (s *Scheduler[T]) Stream(
ctx context.Context,
) <-chan Result[T]


где результаты приходят сразу после завершения задач, а не после окончания всего batch.

Ещё сложнее:


priority queue;
dynamic worker count;
graceful shutdown;
metrics через expvar;
retry только для определённых типов ошибок;
panic recovery внутри job;
benchmark;
fuzz tests.


Главный вопрос

Как реализовать Scheduler так, чтобы одновременно обеспечить:

bounded concurrency + cancellation + ordering + retries + no goroutine leaks + no races

Читать полностью…

Go tests

👣 Go 1.27: почему две разные closure внезапно могут иметь одинаковый адрес функции?

Что выведет этот код и почему на Go 1.27 поведение стало особенно интересным?


package main

import (
"fmt"
"reflect"
)

func makeFn(x int) func() int {
return func() int {
return x
}
}

func main() {
a := makeFn(10)
b := makeFn(20)

pa := reflect.ValueOf(a).Pointer()
pb := reflect.ValueOf(b).Pointer()

fmt.Println(a(), b())
fmt.Println(pa == pb)
}


Интуитивно хочется сказать:

a и b замыкают разные значения, значит это две разные функции и адреса должны отличаться.

Но в Go 1.27 компилятор стал агрессивнее объединять одинаковый машинный код function literals.

У a и b может быть:

один и тот же code pointer
но разное closure data
поэтому a() возвращает 10, а b() - 20

То есть функция в Go на уровне runtime - это не просто адрес машинного кода.

У замыкания фактически есть ещё окружение с захваченными данными.

Именно поэтому сравнивать функции по reflect.Value.Pointer() как способ определить, «одна ли это функция», нельзя.

Go 1.27 специально предупреждает: разные closure с разными захваченными данными теперь могут чаще иметь одинаковые code pointers из-за оптимизаций компилятора.

Читать полностью…

Go tests

Задача Go 1.26, на которой легко ошибиться даже опытному разработчику

Что выведет этот код?


package main

import "fmt"

type Config struct {
Timeout *int
}

func main() {
a := Config{
Timeout: new(30),
}

b := a
*b.Timeout = 60

c := Config{
Timeout: new(*a.Timeout),
}
*c.Timeout = 90

fmt.Println(
*a.Timeout,
*b.Timeout,
*c.Timeout,
)
}


Попробуйте определить ответ до запуска.

```text
60 60 90
```

Почему?

```go
b := a
```

Структура копируется, но указатель внутри неё остаётся тем же. Поэтому `a.Timeout` и `b.Timeout` указывают на одну переменную:

```go
*b.Timeout = 60
```

Изменение видно через обе структуры.

А здесь создаётся уже новая переменная:

```go
Timeout: new(*a.Timeout)
```

Go сначала получает значение `60`, затем выделяет для него отдельную память. Поэтому изменение `c.Timeout` не влияет на `a` и `b`.

```text
a ─┐
├──► 60
b ─┘

c ─────► 90
```

Это важный нюанс: копирование структуры с указателями, слайсами или map не создаёт глубокую копию данных.

Синтаксис `new(30)` появился в **Go 1.26**. Раньше `new` принимал только тип, а теперь может сразу создать указатель на переданное значение.

Код актуален для последней стабильной версии **Go 1.26.5**.

#Golang #Go126 #Programming

Читать полностью…

Go tests

🧠 Редкая задача для Go-разработчиков

Версия: Go 1.23+
Именно в Go 1.23 появился range по функциям-итераторам и пакет iter.

Нужно реализовать:


func MergeSorted(a, b iter.Seq[int]) iter.Seq[int]


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

Пример:


a := Seq(1, 4, 7, 10)
b := Seq(2, 3, 8, 9)

for v := range MergeSorted(a, b) {
fmt.Println(v)
}


Результат:


1 2 3 4 7 8 9 10


Но есть условия:

* нельзя превращать входы в []int;
* нельзя использовать горутины и каналы;
* память должна быть O(1);
* если внешний цикл сделал break, оба исходных итератора должны прекратить работу;
* каждый элемент исходного iterator можно получить только один раз.

🔥 Дополнительный уровень: сделать generic-версию:


func MergeSorted[T cmp.Ordered](
a, b iter.Seq[T],
) iter.Seq[T]


На первый взгляд обычный merge. На практике придётся хорошо понять, как устроены push/pull iterators, `yield` и раннее завершение `range` в Go 1.23.

Читать полностью…

Go tests

В Go 1.26 появился типобезопасный errors.AsType, который ищет ошибку нужного типа внутри дерева обёрток.


package main

import (
"errors"
"fmt"
)

type CodeError struct {
Code int
}

func (e *CodeError) Error() string {
return fmt.Sprintf("code=%d", e.Code)
}

type MaskError struct {
Value int
}

func (e MaskError) Error() string {
return "masked"
}

func (e MaskError) As(target any) bool {
dst, ok := target.(**CodeError)
if !ok {
return false
}

*dst = &CodeError{Code: e.Value}
return true
}

func main() {
err := errors.Join(
fmt.Errorf("left: %w", MaskError{Value: 10}),
errors.Join(
&CodeError{Code: 20},
fmt.Errorf("right: %w", &CodeError{Code: 30}),
),
)

result, ok := errors.AsType[*CodeError](err)
fmt.Println(ok, result.Code)
}


Что будет выведено?

true 10

Кажется, ответ должен быть 20: это первая настоящая ошибка типа *CodeError. Но errors.AsType обходит дерево в глубину, начиная с первой ветки.

MaskError встречается раньше и через собственный метод As притворяется *CodeError, записывая значение с кодом 10. Поэтому дальнейший поиск прекращается.

Cлучай, когда тип ошибки определяется не только её реальным типом, но и поведением метода As.

Читать полностью…

Go tests

👣 Go давно починил старую ловушку с замыканиями в цикле.

Но concurrency всё ещё может кусаться.

Что не так с этим кодом?


package main

import (
"fmt"
"sync"
)

func main() {
nums := []int{1, 2, 3, 4}

var wg sync.WaitGroup
result := make([]int, 0, len(nums))

for i, n := range nums {
wg.Go(func() {
result = append(result, i*n)
})
}

wg.Wait()

fmt.Println(result)
}


На первый взгляд всё нормально.

i и n уже не общие для всех итераций. В современном Go каждая итерация получает свои переменные, поэтому старого бага с замыканием тут нет.

Проблема в другом месте.

`append` меняет slice header и может трогать общий backing array. Несколько горутин делают это одновременно. Значит, здесь data race, даже если loop variables теперь безопасные.

Правильный вариант:

```go id="9f32ws"
package main

import (
"fmt"
"sync"
)

func main() {
nums := []int{1, 2, 3, 4}

var wg sync.WaitGroup
result := make([]int, len(nums))

for i, n := range nums {
wg.Go(func() {
result[i] = i * n
})
}

wg.Wait()

fmt.Println(result)
}
```

Теперь каждая горутина пишет в свой индекс.

Без mutex.
Без channel.
Без лишнего копирования переменных.

Хороший тест на то, понимаешь ли ты Go после 1.22, а не просто помнишь старую страшилку про closures.

Читать полностью…

Go tests

Собираетесь к нам в Go?

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

Другие инженерные инсайты от 2ГИС → в Telegram-канале RnD

Читать полностью…

Go tests

Для тех, кто строит и масштабирует сервисы на Go: 25 апреля пройдет Я.Субботник по Go

Яндекс проведет митап офлайн в Санкт-Петербурге и онлайн. Участников будут ждать практические доклады, живые кейсы и решения, проверенные под нагрузкой.

Руководитель группы разработки Городских сервисов Владимир Тельбухов покажет, как наладить консистентность в интеграциях с внешними сервисами. А разработчик Yandex Cloud Иван Похабов, расскажет, как устроен GoBGP, какие баги в нём встречаются и как их исправляют в production. Полную программу выступлений можно найти на сайте.

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

👉 Регистрируемся

Читать полностью…

Go tests

🔍Тестовое собеседование с Go Senior из Uzum в этот четверг

9 апреля(в четверг!) в 19:00 по мск приходи онлайн на открытое собеседование, чтобы посмотреть на настоящее интервью на Middle Go-разработчика.

Как это будет:
📂 Маруф Караев, Senior из Uzum, ex-Яндекс, ex-EPAM будет задавать реальные вопросы и задачи разработчику-добровольцу
📂 Маруф будет комментировать каждый ответ респондента, чтобы дать понять, чего от вас ожидает собеседующий на интервью
📂 В конце можно будет задать любой вопрос Маруфу

Это бесплатно. Эфир проходит в рамках менторской программы от ШОРТКАТ для Go-разработчиков, которые хотят повысить свой грейд, ЗП и прокачать скиллы.

Переходи в нашего бота, чтобы получить ссылку на эфир →
@shortcut_go_bot

Реклама.
О рекламодателе.

Читать полностью…

Go tests

Скоро стартует F1 для Go-инженеров — VK JT Meetup

VK приглашает обсудить реальные архитектурные кейсы, а также новости и вызовы индустрии.

Когда и где:
📍 Москва — 4 апреля
📍 Санкт-Петербург — 11 апреля

Только офлайн. В программе технические доклады, командные активности и общение.

Москва:
• как сократить число проверок прав с 400 млн до 200 тысяч, не сломав бизнес-логику
• устройство безопасной архитектуры платформы мини-приложений: изоляция, мультитенантность, контроль ресурсов и границы ответственности между платформой и разработчиком

Дальше два трека на выбор: решение архитектурной задачи в команде с обратной связью от лидов VK или обсуждение инженерных новостей в записи подкаста. А в завершение встречи — неформальная вечеринка с коллегами.

Санкт-Петербург:
• устройство безопасной архитектуры платформы мини-приложений: изоляция, мультитенантность, контроль ресурсов и границы ответственности между платформой и разработчиком
• как сделать клиент для Tarantool на Go по-настоящему быстрым — от наивной реализации до оптимизаций, которые режут аллокации и горутины
После докладов — решение архитектурной задачи и живое общение с экспертами VK и коллегами.

Участие бесплатное. Регистрируйтесь по ссылке и приходите!

Читать полностью…

Go tests

👣 Задача: что выведет программа?


package main

import "fmt"

func main() {
for i := 0; i < 3; i++ {
defer fmt.Println(i)
}

for i := 0; i < 3; i++ {
defer func() {
fmt.Println(i)
}()
}

for i := 0; i < 3; i++ {
i := i
defer func() {
fmt.Println(i)
}()
}
}


Ответ: https://go.dev/play/p/pntndQy2jzo

Читать полностью…

Go tests

🧠 Хитрая Go-задача про интерфейсы и память (x64)

Код:


package main

import (
"fmt"
"unsafe"
)

type Foo struct {
A int64
}

type IFoo interface {
Get() int64
}

func (f Foo) Get() int64 { return f.A }

func main() {
var a int64 = 10
var s Foo = Foo{A: 42}
var i IFoo = s

fmt.Println(unsafe.Sizeof(a))
fmt.Println(unsafe.Sizeof(s))
fmt.Println(unsafe.Sizeof(i))
}


Вопросы
• Сколько байт занимает a на x64?
• Сколько байт занимает s?
• Сколько байт занимает i?
• Почему размер i не равен размеру Foo?
• Что реально хранится внутри interface{} в Go?

Разберём по шагам, как это работает в Go на x64.

Код:
```go
var a int64 = 10
var s Foo = Foo{A: 42}
var i IFoo = s
```
1) Размер a
unsafe.Sizeof(a)
```go
int64 = 8 байт
```
На x64:

a = 8 байт
2) Размер s
```go
type Foo struct {
A int64
}```

В структуре одно поле int64.
```go
s = 8 байт
```
3) Размер интерфейса i
```go
var i IFoo = s
unsafe.Sizeof(i)
```go
На x64:
```go
i = 16 байт```


Запустить код: https://go.dev/play/p/NLIG3q-jFc9

Читать полностью…

Go tests

В Go nil - это не просто «пусто».
Иногда это причина самых странных багов в продакшене.

nil в Go - это не одно значение, а множество разных nil.


1. Interface и nil — ловушка


var err error = nil
fmt.Println(err == nil) // true

var e *MyError = nil
var err error = e
fmt.Println(err == nil) // false (!)


Почему так?

Интерфейс в Go хранит:

• тип
• значение

В этом случае:

• тип = *MyError

• значение = nil

Интерфейс не nil, потому что тип задан.

Именно так появляются ошибки вида:

if err != nil срабатывает

но внутри на самом деле nil


2. Typed nil vs untyped nil
var p *int = nil
var s []int = nil
var m map[string]int = nil


Все они nil, но разных типов.
И Go сравнивает не только значение, но и тип.


3. Panic из-за nil внутри interface
type User struct{}

func (u *User) Name() string {
return "John"
}

var u *User = nil
var i interface{} = u

i.(*User).Name() // panic


Интерфейс не nil → метод вызывается → внутри nil → panic.

4. Частый баг с error

Плохой код:

func do() error {
var e *MyError = nil
return e
}


Правильно:

func do() error {
if somethingWrong {
return &MyError{}
}
return nil
}

Главное правило

Если работаешь с interface:
• всегда проверяй, что возвращаешь чистый nil

помни:

interface != nil, если внутри typed nil


https://sushantdhiman.dev/nil-in-go-is-not-what-you-think/

Читать полностью…

Go tests

👣 Понимание выравнивания памяти в Go

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

Что такое выравнивание?

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

Например:
- int64 требует выравнивания по 8 байтам
- int32 - по 4 байтам
- byte - по 1 байту

Если значение лежит “неудобно”, CPU делает несколько операций вместо одной - это медленнее.

Почему появляется padding

Компилятор Go автоматически вставляет пустые байты (padding) между полями структуры, чтобы соблюсти правила выравнивания.

Размер структуры - это не просто сумма размеров полей.

Пример:


type Example struct {
a byte // 1 байт
b int64 // 8 байт (нужно выравнивание по 8)
c byte // 1 байт
}



Хотя “полезных” данных тут 10 байт, структура занимает больше из-за вставленного паддинга.

Почему это важно

Если структура используется миллионы раз (в кэше, массивах, базах, сетевых пакетах), лишние байты превращаются в:

• большее потребление памяти
• худшее попадание в CPU cache
• падение производительности

Как оптимизировать

• Порядок полей имеет значение.
• Крупные типы лучше ставить первыми:


type Optimized struct {
b int64
a byte
c byte
}



Так компилятору нужно меньше padding, и структура становится компактнее.

Главное правило

В Go порядок полей в структуре влияет на производительность.

Выравнивание памяти - это не микроскопическая оптимизация.
В высоконагруженных системах это даёт реальный прирост скорости и экономию памяти.

Сохрани себе - пригодится при проектировании структур данных.

Больше примеров

Читать полностью…
Subscribe to a channel