Go tests


Гео и язык канала: Россия, Русский
Категория: Технологии


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

Связанные каналы  |  Похожие каналы

Гео и язык канала
Россия, Русский
Категория
Технологии
Статистика
Фильтр публикаций


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 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


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

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

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

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

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

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

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


🧠 Редкая задача для 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.


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

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

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

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

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

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


В 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.


🔥 Хочешь быстрее расти в 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: https://t.me/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: 'https://t.me/addlist/2Ls-snqEeytkMDgy' rel='nofollow'>https://t.me/addlist/2Ls-snqEeytkMDgy
Папка Frontend: https://t.me/addlist/mzMMG3RPZhY2M2Iy

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

ИТ-мемы: t.me/memes_prog
Английский для программистов: t.me/english_forprogrammers
ИИ и технологии: t.me/vistehno
954 ГБ open-source курсов: @courses
ИТ-книги бесплатно: https://t.me/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 давно починил старую ловушку с замыканиями в цикле.

Но 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.


👣 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 test --all
  •   go test -r
  •   go test ./...
  •   go test *
  •   Узнать ответ
301 голосов


❓ Как объявить канал только для чтения в аргументе функции
Опрос
  •   func receive(ch chan-> int)
  •   func receive(ch chan
  •   func receive(ch
  •   func receive(ch readonly chan int)
216 голосов


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


❓ За что отвечает поле New в структуре sync.Pool
Опрос
  •   Функция очистки объектов при GC
  •   Коллбек логирования операций пула
  •   Ограничитель максимального размера пула
  •   Фабрика для создания нового объекта, когда пул пуст
  •   Функция создания пула
383 голосов


❓ В каком случае можно использовать пользовательские типы как ключи в мапе
Опрос
  •   Тип содержит только экспортируемые поля
  •   Тип состоит только из сравнимых полей
  •   Тип реализует интерфейс Stringer
  •   Тип является указателем
47 голосов


❓ Что обозначает параметр GOGC
Опрос
  •   Максимальный размер памяти, доступной приложению
  •   Процент прироста памяти перед запуском сборщика мусора
  •   Количество горутин в программе
  •   Версию компилятора Go
108 голосов


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

Функция должна заполнить срез и мапу,
но сейчас она падает с 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-задача:


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


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


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-задача про интерфейсы и память (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


❓ Какой размер у переменной, типом которой является интерфейс на x64 архитектуре
Опрос
  •   4 байта
  •   8 байт
  •   16 байт
  •   Зависит от интерфейса
146 голосов

Показано 20 последних публикаций.