Go 1.26 (Февраль 2026)
Go 1.26 -- масштабный релиз, затрагивающий фундаментальные аспекты runtime (новый GC), системы типов (self-referential generics) и стабилизирующий несколько экспериментальных фич предыдущих версий.
Green Tea GC -- новый сборщик мусора
Go 1.26 представил новый сборщик мусора под кодовым названием Green Tea GC, который заменяет concurrent mark-sweep GC, используемый с Go 1.5. Это самое значительное изменение в runtime Go за последнее десятилетие.
Проблемы старого GC
Предыдущий GC (concurrent tri-color mark-sweep) имел ряд ограничений:
| Проблема | Описание |
|---|---|
| Tail latency | P99 GC-паузы могли достигать десятков миллисекунд при больших heap |
| Short-lived allocations | Объекты с коротким временем жизни создавали нагрузку на GC |
| Write barrier overhead | Барьеры записи замедляли все операции записи указателей |
| Fragmentation | Фрагментация heap при долгоработающих сервисах |
Как работает Green Tea GC
Green Tea GC использует региональную (region-based) модель с элементами arena-allocation:
┌─────────────────────────────────────────┐
│ Heap │
│ ┌──────────┐ ┌──────────┐ ┌────────┐│
│ │ Region 1 │ │ Region 2 │ │Region 3││
│ │ (young) │ │ (young) │ │(tenured)││
│ │ ┌──┐┌──┐ │ │ ┌──┐┌──┐ │ │ ┌──┐ ││
│ │ │A ││B │ │ │ │C ││D │ │ │ │E │ ││
│ │ └──┘└──┘ │ │ └──┘└──┘ │ │ └──┘ ││
│ └──────────┘ └──────────┘ └────────┘│
│ ↓ Full ↓ Partial │
│ Collect Keep surviving │
│ entire objects → tenured │
│ region │
└─────────────────────────────────────────┘
Ключевые идеи:
- Регионы (regions): Heap разделён на регионы фиксированного размера
- Generational hint: Новые объекты попадают в "молодые" регионы
- Region collection: GC может собрать весь регион целиком, если все объекты в нём мертвы
- Arena-like fast path: Выделение в регионе -- это сдвиг указателя (bump pointer)
Практическое влияние
// Benchmark: HTTP server handling 10K requests/sec with 1GB heap
// Measuring GC pause times (P99)
// Go 1.25 (old GC):
// P50: 0.3ms, P99: 8.5ms, P99.9: 25ms
// GC CPU overhead: ~5%
// Go 1.26 (Green Tea GC):
// P50: 0.1ms, P99: 1.2ms, P99.9: 3ms
// GC CPU overhead: ~3%
Бенчмарк: short-lived allocations
func BenchmarkShortLived(b *testing.B) {
for b.Loop() {
// Allocate and immediately discard
m := make(map[string]int, 100)
for i := range 100 {
m[fmt.Sprintf("key_%d", i)] = i
}
// m becomes garbage immediately
}
}
// Go 1.25: BenchmarkShortLived-8 ~15000 ns/op ~8500 B/op
// Go 1.26: BenchmarkShortLived-8 ~9000 ns/op ~8500 B/op
// Same allocations, but faster GC reclamation
Настройка Green Tea GC
# GOMEMLIMIT and GOGC still work
GOMEMLIMIT=1GiB GOGC=100 ./myservice
# New: region size hint (default: auto)
GOREGIONSIZE=2MiB ./myservice
# New: generational mode control
GOGCMODE=generational ./myservice # Default in 1.26
GOGCMODE=concurrent ./myservice # Fallback to old behavior
# Debug: GC tracing
GODEBUG=gctrace=1 ./myservice
Совместимость
Green Tea GC полностью обратно совместим:
- Все программы работают без изменений
runtime.GC(),runtime.ReadMemStats()работают как преждеGOMEMLIMITиGOGCпродолжают работать- Finalizers выполняются (но порядок может отличаться)
Важно: Если вы полагаетесь на конкретное поведение GC (порядок финализаторов, точные моменты сборки), проверьте это. Семантические гарантии Go spec соблюдены, но implementation details могли измениться.
Self-Referential Generics
Go 1.26 снял ограничение на параметры типов, которые ссылаются сами на себя. Это открывает возможности для выразительных рекурсивных структур данных.
Проблема (до Go 1.26)
// ОШИБКА КОМПИЛЯЦИИ в Go < 1.26:
// type Node[T Node[T]] struct { ... }
// Error: invalid recursive type
// Обходной путь был через интерфейсы:
type NodeLike interface {
Children() []NodeLike
}
Решение (Go 1.26+)
// Self-referential type parameter
type Node[T Node[T]] struct {
value string
children []T
}
func (n *Node[T]) AddChild(child T) {
n.children = append(n.children, child)
}
// Concrete implementation
type HTMLElement struct {
Node[HTMLElement]
Tag string
Attributes map[string]string
}
func NewHTMLElement(tag string) *HTMLElement {
return &HTMLElement{
Tag: tag,
Attributes: make(map[string]string),
}
}
Use case: типобезопасное дерево
// Generic tree with self-referential constraint
type Tree[T Tree[T]] interface {
Children() []T
Value() string
}
// File system tree
type FSNode struct {
name string
isDir bool
children []*FSNode
}
func (n *FSNode) Children() []*FSNode { return n.children }
func (n *FSNode) Value() string { return n.name }
// Organization tree
type OrgUnit struct {
name string
manager string
children []*OrgUnit
}
func (o *OrgUnit) Children() []*OrgUnit { return o.children }
func (o *OrgUnit) Value() string { return o.name }
// Generic tree walker works with any self-referential tree
func Walk[T Tree[T]](node T, depth int, visit func(T, int)) {
visit(node, depth)
for _, child := range node.Children() {
Walk(child, depth+1, visit)
}
}
// Usage
func main() {
root := &FSNode{
name: "/",
isDir: true,
children: []*FSNode{
{name: "etc", isDir: true, children: []*FSNode{
{name: "hosts"},
{name: "passwd"},
}},
{name: "home", isDir: true},
},
}
Walk(root, 0, func(node *FSNode, depth int) {
indent := strings.Repeat(" ", depth)
fmt.Printf("%s%s\n", indent, node.name)
})
}
Use case: builder pattern с fluent API
// Builder that returns the concrete type for chaining
type Builder[T Builder[T]] interface {
WithName(string) T
Build() string
}
type UserBuilder struct {
name string
email string
}
func (b *UserBuilder) WithName(name string) *UserBuilder {
b.name = name
return b
}
func (b *UserBuilder) WithEmail(email string) *UserBuilder {
b.email = email
return b
}
func (b *UserBuilder) Build() string {
return fmt.Sprintf("User{name=%s, email=%s}", b.name, b.email)
}
// Type-safe: each method returns the concrete builder type
user := (&UserBuilder{}).
WithName("Alice").
WithEmail("[email protected]").
Build()
Use case: связанный список
type LinkedList[T any, N LinkedNode[T, N]] struct {
head N
size int
}
type LinkedNode[T any, N LinkedNode[T, N]] interface {
Value() T
Next() N
SetNext(N)
}
type SinglyNode[T any] struct {
value T
next *SinglyNode[T]
}
func (n *SinglyNode[T]) Value() T { return n.value }
func (n *SinglyNode[T]) Next() *SinglyNode[T] { return n.next }
func (n *SinglyNode[T]) SetNext(next *SinglyNode[T]) { n.next = next }
crypto/hpke -- Hybrid Public Key Encryption
HPKE (RFC 9180) -- стандарт гибридного шифрования с открытым ключом, объединяющий KEM (Key Encapsulation Mechanism), KDF (Key Derivation Function) и AEAD (Authenticated Encryption).
package main
import (
"crypto/hpke"
"crypto/rand"
"fmt"
)
func main() {
// Setup HPKE suite: KEM + KDF + AEAD
suite := hpke.DHKEM_X25519_SHA256_ChaCha20Poly1305
// Receiver generates key pair
recipientPriv, recipientPub, err := suite.GenerateKeyPair(rand.Reader)
if err != nil {
panic(err)
}
// Sender encrypts message
message := []byte("Secret message for the recipient")
additionalData := []byte("authenticated but not encrypted")
enc, ciphertext, err := suite.Seal(
recipientPub,
message,
additionalData,
)
if err != nil {
panic(err)
}
fmt.Printf("Encrypted: %x...\n", ciphertext[:16])
// Recipient decrypts
plaintext, err := suite.Open(
recipientPriv,
enc,
ciphertext,
additionalData,
)
if err != nil {
panic(err)
}
fmt.Printf("Decrypted: %s\n", plaintext) // Secret message for the recipient
}
Когда использовать HPKE
| Сценарий | До Go 1.26 | С crypto/hpke |
|---|---|---|
| End-to-end encryption | Ручной ECDH + AES | Одна функция Seal/Open |
| Push notifications | Самодельный протокол | Стандартный HPKE |
| Offline messages | Сложная реализация | Одностороннее шифрование |
| Key encapsulation | Нужен ML-KEM | HPKE с PQ-KEM |
testing/synctest -- стабилизация
После двух релизов в экспериментальном режиме, testing/synctest стабилизирован в Go 1.26.
package circuitbreaker
import (
"testing"
"testing/synctest"
"time"
)
func TestCircuitBreaker(t *testing.T) {
synctest.Run(func() {
cb := NewCircuitBreaker(CircuitBreakerConfig{
MaxFailures: 3,
ResetTimeout: 10 * time.Second,
})
// Initially closed (allowing requests)
if cb.State() != StateClosed {
t.Error("expected closed state")
}
// Fail 3 times -> should open
for range 3 {
cb.RecordFailure()
}
if cb.State() != StateOpen {
t.Error("expected open state after 3 failures")
}
// Request should be rejected
if cb.Allow() {
t.Error("should not allow requests in open state")
}
// Wait for reset timeout (virtual time!)
synctest.Sleep(10 * time.Second)
// Should be half-open now
if cb.State() != StateHalfOpen {
t.Errorf("expected half-open, got %v", cb.State())
}
// Success should close it
cb.RecordSuccess()
if cb.State() != StateClosed {
t.Error("expected closed after success in half-open")
}
})
}
func TestWorkerPool(t *testing.T) {
synctest.Run(func() {
pool := NewWorkerPool(3) // 3 workers
results := make(chan int, 10)
for i := range 10 {
pool.Submit(func() {
synctest.Sleep(100 * time.Millisecond)
results <- i
})
}
// Fast-forward through all work
synctest.Sleep(400 * time.Millisecond) // ceil(10/3) * 100ms
close(results)
count := 0
for range results {
count++
}
if count != 10 {
t.Errorf("expected 10 results, got %d", count)
}
pool.Shutdown()
})
}
Расширенная поддержка итераторов в stdlib
Go 1.26 добавил итераторы в больше пакетов стандартной библиотеки:
import (
"bufio"
"bytes"
"os"
"strings"
)
// bufio.Scanner returns an iterator
f, _ := os.Open("data.txt")
scanner := bufio.NewScanner(f)
for line := range scanner.Lines() {
fmt.Println(line)
}
// bytes.Lines, bytes.Fields as iterators
data := []byte("hello world\nfoo bar\nbaz")
for line := range bytes.Lines(data) {
fmt.Println(string(line))
}
// strings.Fields as iterator
text := " hello world go "
for field := range strings.Fields(text) {
fmt.Println(field) // "hello", "world", "go"
}
// os.ReadDir returns iterator
for entry := range os.ReadDirIter("/tmp") {
fmt.Println(entry.Name())
}
Производительность Go 1.26
Overall performance improvements vs Go 1.25:
HTTP server throughput: +12% (GC + compiler improvements)
JSON Marshal/Unmarshal: +8% (reduced allocations)
Map operations: +5% (Swiss table refinements)
String concatenation: +15% (improved builder)
Regex matching: +10% (DFA optimization)
Compilation speed: +7% (parallel compilation improvements)
Binary size: -4% (dead code elimination improvements)
Что дальше для Go
Команда Go обозначила несколько направлений развития:
| Направление | Статус | Ожидаемый релиз |
|---|---|---|
| Sum types (union types) | Proposal обсуждается | Go 1.28+ |
| Structured concurrency | Experimental | Go 1.27 |
| Better error handling | Proposal stage | TBD |
| Generic methods | Under discussion | TBD |
| Effect system | Research | Very long term |
Sum types (обсуждение)
// Hypothetical syntax (not final):
type Result[T any] union {
Ok(T)
Err(error)
}
// Or with sealed interfaces:
type Shape sealed interface {
Circle | Rectangle | Triangle
}
Structured concurrency
// Hypothetical (experimental in Go 1.27):
func processOrders(ctx context.Context, orders []Order) error {
g := task.NewGroup(ctx)
for _, order := range orders {
g.Go(func(ctx context.Context) error {
return processOrder(ctx, order)
})
}
return g.Wait() // Waits for all, cancels on first error
}
Сводная таблица Go 1.26
| Фича | Влияние | Действие |
|---|---|---|
| Green Tea GC | Высокое | Автоматическое улучшение P99 latency |
| Self-referential generics | Среднее | Рекурсивные структуры данных |
| crypto/hpke | Среднее | Стандартное гибридное шифрование |
| testing/synctest stable | Высокое | Детерминированные тесты конкурентности |
| Iterator stdlib support | Среднее | for-range по bufio, bytes, os |
| Performance improvements | Высокое | Автоматическое ускорение |
Общая временная шкала Go 1.16 -- 1.26
| Версия | Дата | Главная фича |
|---|---|---|
| 1.16 | Фев 2021 | embed, io/fs |
| 1.17 | Авг 2021 | //go:build, module pruning |
| 1.18 | Мар 2022 | GENERICS, fuzzing, workspaces |
| 1.19 | Авг 2022 | GOMEMLIMIT, atomic types |
| 1.20 | Фев 2023 | PGO preview, errors.Join |
| 1.21 | Авг 2023 | slog, slices/maps/cmp, min/max/clear |
| 1.22 | Фев 2024 | Enhanced ServeMux, loop var fix |
| 1.23 | Авг 2024 | Iterators (range-over-func), unique |
| 1.24 | Фев 2025 | weak pointers, Swiss tables, b.Loop() |
| 1.25 | Авг 2025 | Runtime optimizations, green threads preview |
| 1.26 | Фев 2026 | Green Tea GC, self-referential generics |