Go
остаётся верен себе: — синтакс для обработки ошибок не упростят — новые предложения даже рассматриваться не будут.
С 2018 года команда пыталась: —
check/handle
— try(...)
— даже ?, как в Rust
Итог: три своих предложения, сотни от комьюнити — и ни одно не получило общего одобрения. После стольких итераций архитекторы
Go
говорят прямо: > "We should stop trying to solve the syntactic problem, at least for the foreseeable future."
if err != nil
— это не баг. Это стиль. Go
остаётся многословным — потому что предсказуемость важнее лаконичности.Ссылка на блог
Please open Telegram to view this post
VIEW IN TELEGRAM
👍7 6👀1
Please open Telegram to view this post
VIEW IN TELEGRAM
Please open Telegram to view this post
VIEW IN TELEGRAM
Media is too big
VIEW IN TELEGRAM
Как же здорово, когда вокруг люди, с которыми хочется свернуть горы! ⛰️
Три дня невероятной энергии, общих планов и моментов, которые хочется сохранить в памяти…❤️
Этим роликом хочу передать вам частичку того, что мы пережили.
Три дня невероятной энергии, общих планов и моментов, которые хочется сохранить в памяти…
Этим роликом хочу передать вам частичку того, что мы пережили.
Please open Telegram to view this post
VIEW IN TELEGRAM
❤13👍5🔥5
В версию
go
1.24
weak
, который позволяет создавать слабые указатели — ссылки на объекты, которые не мешают сборщику мусора освободить память.В отличие от обычных указателей, слабые не удерживают объект в памяти. Если на объект больше никто не ссылается, кроме слабого указателя, он может быть удалён.
📦 Пример:
wb := weak.Make(newBlob(1000)) // создаём слабый указатель на объект
fmt.Println("before GC =", wb.Value()) // объект ещё доступен
runtime.GC() // запускаем сборщик мусора
fmt.Println("after GC =", wb.Value()) // возможно, объект уже удалён → вернёт nil
Если объект больше не используется,
wb.Value()
может вернуть nil
после сборки мусора.Для сравнения, обычный указатель не даст объекту исчезнуть:
b := newBlob(1000) // обычный указатель на объект
fmt.Println("before GC =", b) // объект доступен
runtime.GC() // запускаем сборщик мусора
fmt.Println("after GC =", b) // объект всё ещё в памяти — указатель его "удерживает"
Рантайм
сам решает, когда и что очищать.#слабые #указатели
Please open Telegram to view this post
VIEW IN TELEGRAM
1 10❤4🔥3
Go 1.25
: Тесты без ожиданийВ релизе
Go 1.25
наконец стабилизировали synctest
— теперь можно использовать его без оглядки на экспериментальный статус.Этот пакет пригодится тем, кто когда-либо писал тесты с time.Sleep, time.After, time.NewTimer и другими блокирующими операциями.
synctest
предоставляет виртуальные часы, которые сами идут вперёд, если тестируемая горутина ждёт.Например, обычная функция:
func SlowThing() int {
start := time.Now()
time.Sleep(15 * time.Second)
fmt.Println("done in", time.Since(start))
return 7
}
Раньше её тест нужно было ждать
15 секунд
. Теперь всё можно обернуть в synctest.Test
— и проверка произойдёт мгновенно:func TestSlowThing(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
if SlowThing() != 7 {
t.Error("unexpected result")
}
})
}
Результат:
=== RUN TestSlowThing
done in 15s
--- PASS: TestSlowThing (0.00s)
#go1_25
1.25
: тесты таймеров и select
без задержекЕсли вы когда-либо писали тесты с
time.Sleep
, time.After
или time.Ticker
, вы наверняка заметили, что на каждый «таймаут» уходит реальное время. В больших наборах тестов это может растянуть прогон CI
до бесконечности.Пакет
synctest
подменяет системные часы на «фейковые»: ваши тесты мгновенно прыгают вперёд, не ожидая 5 или 10 секунд.Установите пакет:
go get github.com/your/repo/synctest
В тестах оборачивайте логику в synctest.Test:
synctest.Test(t, func(t *testing.T) {
// ваш код с таймерами
})
time.After
vs time.NewTimer
synctest.Test(t, func(t *testing.T) {
afterCh := time.After(5 * time.Second)
timer := time.NewTimer(10 * time.Second)
select {
case <-afterCh:
fmt.Println("after fired first")
case <-timer.C:
fmt.Println("timer fired first")
}
})
time.After(5s)
возвращает канал, который сработает через 5 секунд.time.NewTimer(10s)
даёт канал, который сработает через 10 секунд.Fake clock
мгновенно перематывает на +5
секунд, и мы сразу видим after fired first
, без реального ожидания.time.Ticker
synctest.Test(t, func(t *testing.T) {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
first := <-ticker.C
second := <-ticker.C
fmt.Println("ticks at:", first, second)
})
NewTicker(3s)
запускает «тиковый» канал каждые 3 секунды.Fake clock
сразу делает два прыжка по 3 секунды, и оба чтения <-ticker
.C выполняются без задержек.Please open Telegram to view this post
VIEW IN TELEGRAM
PRO Go
🔥 Как работает синтетическое время в Go 1.25?
⚙️ Пузырь и виртуальные часы. Когда вы вызываете
🕒 не идут сами по себе — они стоят на месте💪 двигаются только тогда, когда все
👉 Если одна горутина спит
🔄 Что считается «заблокированной» горутиной?
✅
❌ внешние каналы, сетевые операции и другие
🧪 Что делает
#select #синтетическоевремя
⚙️ Пузырь и виртуальные часы. Когда вы вызываете
synctest.Test(...)
, создается изолированный пузырь — тестовую среду с отдельными часами. Эти часы:🕒 не идут сами по себе — они стоят на месте
горутины
внутри пузыря заблокированы (например, ждут Sleep, select,
канал или WaitGroup
)👉 Если одна горутина спит
15 секунд
, а другие ничего не делают — synctest
просто проматывает время на +15
секунд и продолжает выполнение. Тест проходит мгновенно.✅
time.Sleep
✅ чтение/запись на канале внутри пузыря ✅ sync.WaitGroup.Wait
, sync.Cond.Wait
✅ select
, где все ветки — блокирующие❌ внешние каналы, сетевые операции и другие
I/O
— не считаются, время не проматывается.🧪 Что делает
synctest.Wait()
? Она ждёт, пока все горутины внутри пузыря станут заблокированы — полезно для проверки фоновых задач перед утверждением результата.#select #синтетическоевремя
Please open Telegram to view this post
VIEW IN TELEGRAM
Go 1.25 Release Candidate 3
уже доступен!os/exec.LookPath
мог возвращать путь к бинарям, если PATH
содержал исполняемые файлы вместо директорий — теперь поведение корректно (CVE‑2025‑47906
).database/sql.Rows.Scan
иногда возвращал некорректные значения — баг устранён.Please open Telegram to view this post
VIEW IN TELEGRAM
JavaScript
, то знаете связку async/await
: оборачиваем функцию в async
, а потом в другом месте делаем await
, чтобы дождаться результата.В
Go
такого синтаксиса нет… но мы можем им прикинуться. С помощью каналов и горутин получится что‑то похожее.fn := async(func() any {
return "Hello, JavaScript!"
})
res := await(fn)
fmt.Println(res)
// Hello, JavaScript!
async
— принимает функцию, запускает её в отдельной горутине и возвращает канал, по которому придёт результат.await
— просто читает из канала и возвращает то, что туда положили.func async(f func() any) <-chan any {По сути:
out := make(chan any, 1) // буфер, чтобы горутина не блокировалась
go func() {
defer close(out)
out <- f() // выполняем функцию и отправляем результат
}()
return out
}
func await(in <-chan any) any {
return <-in // ждём данные из канала
}
async
→ заворачивает работу в горутину + канал.await
→ читает результат из канала, синхронно дожидаясь окончания работы.Go
уже есть привычные подходы к конкурентности через goroutine + channel
или sync.WaitGroup
. Но как способ пошутить над синтаксисом — почему бы и нет.Please open Telegram to view this post
VIEW IN TELEGRAM
This media is not supported in your browser
VIEW IN TELEGRAM
Когда 💪
Go
-разработчик получил свою первую зарплатуPlease open Telegram to view this post
VIEW IN TELEGRAM
😁24🤣11