пятница, 17 июля 2026 г.

Релиз Go 1.26

Последний релиз Go, версия 1.26, выходит в феврале 2026 года, спустя шесть месяцев после Go 1.25. Большинство изменений касаются инструментов сборки, среды исполнения и библиотек. Как и раньше, релиз сохраняет совместимость с обещаниями Go 1. Ожидается, что почти все программы на Go продолжат компилироваться и выполняться аналогично предыдущим версиям.

Изменения в языке

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

Эта возможность особенно полезна при работе с пакетами сериализации, такими как encoding/json или Protocol Buffers, которые используют указатель для представления необязательного значения, поскольку позволяет заполнить необязательное поле простым выражением:

import "encoding/json"

type Person struct {
    Name string   `json:"name"`
    Age  *int     `json:"age"` // возраст, если известен; иначе nil
}

func personJSON(name string, born time.Time) ([]byte, error) {
    return json.Marshal(Person{
        Name: name,
        Age:  new(yearsSince(born)),
    })
}

func yearsSince(t time.Time) int {
    return int(time.Since(t).Hours() / (365.25 * 24)) // приблизительно
}

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

type Adder[A Adder[A]] interface {
    Add(A) A
}

func algo[A Adder[A]](x, y A) A {
    return x.Add(y)
}

Ранее ссылка на Adder в первой строке не допускалась. Помимо расширения возможностей ограничений типов, это изменение несколько упрощает правила спецификации для параметров типов.

Инструменты

Команда go

Знаковая команда go fix была полностью переработана и теперь является домом для модернизаторов Go. Она обеспечивает надёжный способ обновления кодовой базы Go до современных идиом и API стандартной библиотеки. Начальный набор модернизаторов включает десятки инструментов для использования новейших возможностей языка Go и библиотеки, а также инлайнатор на уровне исходного кода, позволяющий автоматизировать собственные миграции API с помощью директив //go:fix inline.

Переписанная команда go fix построена на том же фреймворке анализа Go, что и go vet. Это означает, что одни и те же анализаторы, которые предоставляют диагностику в go vet, могут использоваться для предложения и применения исправлений в go fix. Исторические фиксеры команды go fix, все из которых были устаревшими, были удалены.

go mod init теперь по умолчанию использует более низкую версию go в новых файлах go.mod. Запуск go mod init с инструментарием версии 1.N.X создаст файл go.mod с версией Go go 1.(N-1).0. Предрелизные версии 1.N будут создавать файлы go.mod с указанием go 1.(N-2).0. Например, кандидаты в релиз Go 1.26 создадут файлы go.mod с go 1.24.0, а Go 1.26 и его минорные релизы — с go 1.25.0. Это призвано поощрять создание модулей, совместимых с текущими поддерживаемыми версиями Go.

Команды cmd/doc и go tool doc были удалены. В качестве замены можно использовать go doc: он принимает те же флаги и аргументы и ведёт себя аналогично.

Pprof

Веб-интерфейс инструмента pprof, включаемый флагом -http, теперь по умолчанию отображает представление пламени (flame graph). Предыдущее графическое представление доступно в меню «View → Graph» или по адресу /ui/graph.

Среда исполнения (runtime)

Новый сборщик мусора

Сборщик мусора Green Tea, доступный ранее как эксперимент в Go 1.25, теперь включён по умолчанию после обработки отзывов.

Дизайн этого сборщика мусора улучшает производительность разметки и сканирования мелких объектов за счёт лучшей локальности и масштабируемости на несколько ядер CPU. Результаты бенчмарков варьируются, но ожидается снижение накладных расходов на сборку мусора примерно на 10–40% в реальных приложениях, активно использующих сборку мусора. Дальнейшие улучшения порядка 10% ожидаются на более новых платформах на базе amd64 (Intel Ice Lake или AMD Zen 4 и новее), поскольку сборщик мусора теперь использует SIMD-инструкции для сканирования мелких объектов, когда это возможно.

Новый сборщик мусора может быть отключён установкой переменной GOEXPERIMENT=nogreenteagc при сборке. Эта настройка отключения, как ожидается, будет удалена в Go 1.27.

Более быстрые cgo-вызовы

Базовые накладные расходы среды исполнения на cgo-вызовы сокращены примерно на 30%.

Рандомизация базового адреса кучи

На 64-битных платформах среда исполнения теперь рандомизирует базовый адрес кучи при запуске. Это улучшение безопасности, затрудняющее злоумышленникам предсказание адресов памяти и эксплуатацию уязвимостей при использовании cgo. Эта функция может быть отключена установкой GOEXPERIMENT=norandomizedheapbase64 при сборке.

Экспериментальный профиль утечек горутин

Новый тип профиля, сообщающий об утечках горутин, доступен как эксперимент. Новый тип профиля, названный goroutineleak в пакете runtime/pprof, может быть включён установкой GOEXPERIMENT=goroutineleakprofile при сборке. Включение эксперимента также делает профиль доступным в качестве эндпоинта net/http/pprof: /debug/pprof/goroutineleak.

Утечная горутина — это горутина, заблокированная на некотором примитиве синхронизации (каналы, sync.Mutex, sync.Cond и т.д.), который не может стать разблокированным. Среда исполнения обнаруживает утечные горутины с помощью сборщика мусора: если горутина G заблокирована на примитиве P, и P недостижим из какой-либо запускаемой горутины или из горутин, которые эти могут разблокировать, то P не может быть разблокирован, и горутина G никогда не проснётся.

Следующий пример демонстрирует реальную утечку горутин, которую можно выявить с помощью нового профиля:

type result struct {
    res workResult
    err error
}

func processWorkItems(ws []workItem) ([]workResult, error) {
    ch := make(chan result)
    for _, w := range ws {
        go func() {
            res, err := processWorkItem(w)
            ch <- result{res, err}
        }()
    }

    var results []workResult
    for range len(ws) {
        r := <-ch
        if r.err != nil {
            // Этот ранний выход может вызвать утечку горутин.
            return nil, r.err
        }
        results = append(results, r.res)
    }
    return results, nil
}

Поскольку ch небуферизированный, если processWorkItems завершается раньше времени из-за ошибки, все оставшиеся горутины processWorkItem утекут. Вскоре после этого ch станет недостижим для всех других горутин, не связанных с утечкой, что позволит среде исполнения обнаружить и сообщить об утечных горутинах.

Реализация является готовой к продакшну и считается экспериментом только в целях сбора отзывов об API. Планируется включить профили утечек горутин по умолчанию в Go 1.27.

Компилятор

Компилятор теперь может размещать хранилище данных срезов на стеке в большем количестве случаев, что повышает производительность. Если это изменение вызывает проблемы, можно воспользоваться инструментом bisect с флагом -compile=variablemake для поиска проблемного выделения. Все новые стековые выделения также можно отключить с помощью -gcflags=all=-d=variablemakehash=n.

Линкер

На 64-битном ARM Windows (windows/arm64) линкер теперь поддерживает внутренний режим связывания программ cgo, который можно запросить флагом -ldflags=-linkmode=internal.

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

  • Структура moduledata теперь размещена в собственном секции .go.module.
  • Поле cutab структуры moduledata теперь имеет правильную длину; ранее длина была в четыре раза больше.
  • pcHeader в начале секции .gopclntab больше не записывает начало секции .text. Это поле теперь всегда равно нулю.
  • Секция .gopclntab более не содержит релокаций. На платформах с relro секция перемещена из сегмента relro в сегмент rodata.
  • Символы funcdata и findfunctab перемещены из секции .rodata в .gopclntab.
  • Секция .gosymtab удалена.
  • При использовании внутреннего режима связывания ELF-секции теперь отсортированы по адресу в заголовке.

Загрузчик (Bootstrap)

Go 1.26 теперь требует Go 1.24.6 или новее для загрузки. Ожидается, что Go 1.28 потребует минорный релиз Go 1.26 или новее.

Стандартная библиотека

Новый пакет crypto/hpke

Новый пакет crypto/hpke реализует гибридное шифрование открытым ключом (HPKE) в соответствии с RFC 9180, включая поддержку постквантовых гибридных KEM.

Новый экспериментальный пакет simd/archsimd

Go 1.26 вводит новый экспериментальный пакет simd/archsimd, который можно включить установкой переменной GOEXPERIMENT=simd при сборке. Этот пакет предоставляет доступ к архитектурно-зависимым SIMD-операциям. В настоящее время он доступен для архитектуры amd64 и поддерживает 128-, 256- и 512-битные векторные типы, такие как Int8x16 и Float64x8, с операциями вроде Int8x16.Add. API ещё не считается стабильным.

Планируется предоставить поддержку других архитектур в будущих версиях, но API намеренно архитектурно-зависим и, следовательно, не переносим.

Новый экспериментальный пакет runtime/secret

Новый пакет runtime/secret доступен как эксперимент, который можно включить установкой GOEXPERIMENT=runtimesecret при сборке. Он предоставляет механизм для безопасного стирания временных данных в коде, работающем с секретной информацией — как правило, криптографической, — таких как регистры, стек, новые выделения в куче. Этот пакет призван облегчить обеспечение прямой секретности. В настоящее время он поддерживает архитектуры amd64 и arm64 на Linux.

Go 1.26 — Незначительные изменения в библиотеке

bytes

Новый метод Buffer.Peek возвращает следующие n байтов из буфера без продвижения указателя чтения.

crypto

Новые интерфейсы Encapsulator и Decapsulator позволяют принимать абстрактные ключи инкапсуляции или деинкапсуляции KEM.

crypto/dsa

Параметр random в функции GenerateKey теперь игнорируется. Вместо этого теперь всегда используется безопасный источник криптографически случайных байтов. Для детерминированного тестирования используйте новую функцию testing/cryptotest.SetGlobalRandom. Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

crypto/ecdh

Параметр random в методе Curve.GenerateKey теперь игнорируется. Вместо этого теперь всегда используется безопасный источник криптографически случайных байтов. Для детерминированного тестирования используйте новую функцию testing/cryptotest.SetGlobalRandom. Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

Новый интерфейс KeyExchanger, реализуемый типом PrivateKey, позволяет принимать абстрактные приватные ключи ECDH, например, реализованные в аппаратном обеспечении.

crypto/ecdsa

Поля типа big.Int в структурах PublicKey и PrivateKey теперь устарели.

Параметр random в функциях GenerateKey, SignASN1, Sign и методе PrivateKey.Sign теперь игнорируется. Вместо этого теперь всегда используется безопасный источник криптографически случайных байтов. Для детерминированного тестирования используйте новую функцию testing/cryptotest.SetGlobalRandom. Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

crypto/ed25519

Если параметр random в функции GenerateKey равен nil, то GenerateKey теперь всегда использует безопасный источник криптографически случайных байтов вместо crypto/rand.Reader (который мог быть переопределён). Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

crypto/fips140

Криптографический модуль Go, соответствующий FIPS 140-3 v1.26.0 включает изменения, внесённые в пакеты crypto/internal/fips140/... вплоть до этого выпуска, и теперь может быть выбран с помощью GOFIPS140.

Новые функции WithoutEnforcement и Enforced позволяют работать в режиме GODEBUG=fips140=only, при этом выборочно отключая строгие проверки FIPS 140-3.

Функция Version возвращает разрешённую версию криптографического модуля Go, соответствующего FIPS 140-3, при сборке с замороженным модулем через GOFIPS140.

crypto/mlkem

Новые методы DecapsulationKey768.Encapsulator и DecapsulationKey1024.Encapsulator реализуют новый интерфейс crypto.Decapsulator.

Операции инкапсуляции и деинкапсуляции теперь выполняются примерно на 18% быстрее.

crypto/mlkem/mlkemtest

Новый пакет crypto/mlkem/mlkemtest предоставляет функции Encapsulate768 и Encapsulate1024, которые реализуют детерминизированную инкапсуляцию ML-KEM для использования в тестах на основе заранее известных ответов (known-answer tests).

crypto/rand

Параметр random в функции Prime теперь игнорируется. Вместо этого теперь всегда используется безопасный источник криптографически случайных байтов. Для детерминированного тестирования используйте новую функцию testing/cryptotest.SetGlobalRandom. Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

crypto/rsa

Новая функция EncryptOAEPWithOptions позволяет указывать различные функции хеширования для дополнения OAEP и генерации маски MGF1.

Параметр random в функциях GenerateKey, GenerateMultiPrimeKey и EncryptPKCS1v15 теперь игнорируется. Вместо этого теперь всегда используется безопасный источник криптографически случайных байтов. Для детерминированного тестирования используйте новую функцию testing/cryptotest.SetGlobalRandom. Новая настройка GODEBUG cryptocustomrand=1 временно восстанавливает старое поведение.

Если поля PrivateKey изменяются после вызова PrivateKey.Precompute, то PrivateKey.Validate теперь завершается ошибкой.

Поле PrivateKey.D теперь проверяется на согласованность с предвычисленными значениями, даже если оно не используется.

Небезопасное дополнение шифрования PKCS #1 v1.5 (реализуемое функциями EncryptPKCS1v15, DecryptPKCS1v15 и DecryptPKCS1v15SessionKey) теперь устарело.

crypto/sha3

Нулевое значение SHA3 теперь является пригодным для использования экземпляром SHA3-256, а нулевое значение SHAKE теперь является пригодным для использования экземпляром SHAKE256.

crypto/subtle

Функция WithDataIndependentTiming больше не привязывает вызывающую горутину к потоку ОС во время выполнения переданной функции. Кроме того, любые горутины, порождённые во время выполнения переданной функции, и их потомки теперь наследуют свойства WithDataIndependentTiming на время своего существования. Это изменение также затрагивает cgo следующим образом:

  • Любой C-код, вызванный через cgo изнутри функции, переданной в WithDataIndependentTiming, или из горутины, порождённой функцией, переданной в WithDataIndependentTiming, и её потомков, также будет иметь включённое независимое от данных время выполнения на протяжении вызова. Если C-код отключает независимое от данных время выполнения, оно будет повторно включено при возврате в Go.
  • Если C-код, вызванный через cgo — из функции, переданной в WithDataIndependentTiming, или из любого другого места — включает или отключает независимое от данных время выполнения, то при вызове из Go это состояние сохраняется на протяжении вызова.

crypto/tls

Гибридные постквантовые обмены ключами SecP256r1MLKEM768 и SecP384r1MLKEM1024 теперь включены по умолчанию. Их можно отключить с помощью настройки Config.CurvePreferences или параметра GODEBUG tlssecpmlkem=0.

Новое поле ClientHelloInfo.HelloRetryRequest указывает, было ли сообщение ClientHello отправлено в ответ на сообщение HelloRetryRequest. Новое поле ConnectionState.HelloRetryRequest указывает, отправил ли сервер HelloRetryRequest или получил ли клиент HelloRetryRequest, в зависимости от роли соединения.

Тип QUICConn, используемый реализациями QUIC, включает новое событие для сообщения об ошибках рукопожатия TLS.

Если Certificate.PrivateKey реализует интерфейс crypto.MessageSigner, то его метод SignMessage используется вместо Sign в TLS 1.2 и выше.

Следующие настройки GODEBUG, введённые в Go 1.22 и Go 1.23, будут удалены в следующем мажорном выпуске Go. Начиная с Go 1.27, новое поведение будет применяться независимо от настройки GODEBUG или версии языка в go.mod:

  • tlsunsafeekm: ConnectionState.ExportKeyingMaterial будет требовать TLS 1.3 или расширенное мастер-секрет (Extended Master Secret).
  • tlsrsakex: устаревшие обмены ключами только на основе RSA без ECDH не будут включены по умолчанию.
  • tls10server: минимальная версия TLS по умолчанию как для клиентов, так и для серверов будет TLS 1.2.
  • tls3des: набор шифров по умолчанию не будет включать 3DES.
  • x509keypairleaf: функции X509KeyPair и LoadX509KeyPair всегда будут заполнять поле Certificate.Leaf.

crypto/x509

Типы ExtKeyUsage и KeyUsage теперь имеют методы String, которые возвращают соответствующие имена OID, определённые в RFC 5280 и других реестрах.

Тип ExtKeyUsage теперь имеет метод OID, который возвращает соответствующий OID для EKU (Extended Key Usage).

Новая функция OIDFromASN1OID позволяет преобразовывать encoding/asn1.ObjectIdentifier в OID.

debug/elf

Определены дополнительные константы R_LARCH_* из LoongArch ELF psABI v20250521 (глобальная версия v2.40) для использования в системах на базе LoongArch.

errors

Новая функция AsType является обобщённой (generic) версией функции As. Она типобезопасна, быстрее и, в большинстве случаев, удобнее в использовании.

fmt

Для неформатированных строк fmt.Errorf("x") теперь выделяет меньше памяти и в целом соответствует выделениям errors.New("x").

go/ast

Новая функция ParseDirective разбирает директивные комментарии — комментарии вида //go:generate. Инструменты для работы с исходным кодом могут поддерживать собственные директивные комментарии, и этот новый API должен помочь им реализовать общепринятый синтаксис.

Новое поле BasicLit.ValueEnd фиксирует точную конечную позицию литерала, так что метод BasicLit.End теперь всегда возвращает правильный ответ. (Ранее позиция вычислялся с помощью эвристики, которая была некорректной для многострочных литералов необработанных строк в файлах исходного кода Windows из-за удаления символов возврата каретки.)

Программы, обновляющие поле ValuePos у BasicLit, созданных парсером, могут также потребовать обновления или очистки поля ValueEnd для избежания незначительных различий в форматированном выводе.

go/token

Новый удобный метод File.End возвращает позицию конца файла.

go/types

Настройка GODEBUG gotypesalias, введённая в Go 1.22, будет удалена в следующем мажорном выпуске Go. Начиная с Go 1.27, пакет go/types всегда будет создавать тип Alias для представления псевдонимов типов, независимо от настройки GODEBUG или версии языка в go.mod.

image/jpeg

Кодер и декодер JPEG заменены на новые, более быстрые и точные реализации. Код, рассчитывающий на конкретные побитовые результаты кодера или декодера, может потребовать обновления.

io

ReadAll теперь выделяет меньше промежуточной памяти и возвращает минимально необходимый по размеру итоговый слайс. Функция работает примерно в два раза быстрее, при этом обычно выделяя примерно вдвое меньше общей памяти, с ещё большей выгодой для больших входных данных.

log/slog

Функция NewMultiHandler создаёт MultiHandler, который вызывает все переданные обработчики (Handlers). Метод Enabled возвращает true, если метод Enabled хотя бы одного из обработчиков возвращает true. Методы Handle, WithAttrs и WithGroup вызывают соответствующий метод у каждого из активных обработчиков.

net

Новые методы DialerDialIP, DialTCP, DialUDP и DialUnix — позволяют набирать соединение определённых типов сети с передачей значений контекста.

net/http

Новое поле HTTP2Config.StrictMaxConcurrentRequests управляет тем, следует ли открывать новое соединение, если существующее соединение HTTP/2 превысило свой лимит потоков.

Новый метод Transport.NewClientConn возвращает клиентское соединение с HTTP-сервером. Большинству пользователей следует продолжать использовать Transport.RoundTrip для отправки запросов — он управляет пулом соединений. NewClientConn полезен для пользователей, которым необходимо реализовать собственное управление соединениями.

Client теперь использует и устанавливает cookies, привязанные к URL-адресам, часть host которых совпадает с Реquest.Host, когда это доступно. Ранее всегда использовался host адреса подключения. Перенаправления ServeMux с завершающим слэшем теперь используют HTTP-статус 307 (Временное перенаправление) вместо 301 (Перемещено навсегда).

net/http/httptest

HTTP-клиент, возвращаемый методом Server.Client, теперь будет перенаправлять запросы к example.com и любым поддоменам на тестируемый сервер.

net/http/httputil

Поле конфигурации ReverseProxy.Director устарело в пользу ReverseProxy.Rewrite.

Злонамеренный клиент может удалить заголовки, добавленные функцией Director, обозначив их как заголовки перехода (hop-by-hop). Поскольку нет способа решить эту проблему в рамках API Director, в Go 1.20 был добавлен новый хук Rewrite. Хуки Rewrite получают как неизменённый входящий запрос, полученный прокси, так и исходящий запрос, который будет отправлен прокси.

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

net/netip

Новый метод Prefix.Compare сравнивает два префикса.

net/url

Parse теперь отклоняет неправильно сформированные URL-адреса, содержащие двоеточия в компоненте хоста, такие как http://::1/ или http://localhost:80:80/. URL-адреса, содержащие адреса IPv6 в квадратных скобках, такие как http://[::1]/, по-прежнему принимаются. Новая настройка GODEBUG urlstrictcolons=0 восстанавливает старое поведение.

os

Новый метод Process.WithHandle обеспечивает доступ к внутреннему дескриптору процесса на поддерживаемых платформах (pidfd в Linux 5.4 или новее, Handle в Windows).

В Windows параметр flag функции OpenFile теперь может содержать любую комбинацию специфических для Windows флагов файлов, таких как FILE_FLAG_OVERLAPPED и FILE_FLAG_SEQUENTIAL_SCAN, для управления поведением кэширования файлов или устройств, режимами доступа и другими специальными флагами.

os/signal

NotifyContext теперь отменяет возвращаемый контекст с помощью context.CancelCauseFunc и ошибки, указывающей, какой сигнал был получен.

reflect

Новые методы Type.Fields, Type.Methods, Type.Ins и Type.Outs возвращают итераторы по полям типа (для структурного типа), методам, входным и выходным параметрам (для функционального типа) соответственно.

Аналогично, новые методы Value.Fields и Value.Methods возвращают итераторы по полям или методам значения соответственно. Каждая итерация предоставляет информацию о типе (StructField или Method) поля или метода вместе со значением (Value) поля или метода.

runtime/metrics

Добавлено несколько новых метрик планировщика, включая количество горутин в различных состояниях (ожидающих, исполняемых и т.д.) с префиксом /sched/goroutines, количество потоков ОС, известных рантайму, по адресу /sched/threads:threads, и общее количество горутин, созданных программой, по адресу /sched/goroutines-created:goroutines.

testing

Новые методы T.ArtifactDir, B.ArtifactDir и F.ArtifactDir возвращают каталог для записи выходных файлов тестов (артефактов).

Когда флаг -artifacts передан в go test, этот каталог будет располагаться внутри каталога вывода (указанного с помощью -outputdir или текущего каталога по умолчанию). В противном случае артефакты сохраняются во временном каталоге, который удаляется после завершения теста.

Первый вызов ArtifactDir при использовании -artifacts записывает расположение каталога в журнал теста.

Например, в тесте с именем TestArtifacts вызов t.ArtifactDir() выводит:

=== ARTIFACTS TestArtifacts /path/to/artifact/dir

Метод B.Loop больше не предотвращает встраивание (inlining) в теле цикла, что могло приводить к неожиданным выделениям памяти и замедлению бенчмарков. Благодаря этому исправлению мы ожидаем, что все бенчмарки могут быть переведены со старого стиля B.N на новый стиль B.Loop без каких-либо негативных последствий. Внутри тела цикла for b.Loop() { ... } параметры вызова функций, возвращаемые значения и присваиваемые переменные по-прежнему удерживаются в живости, что не позволяет компилятору оптимизировать целые части бенчмарка.

testing/cryptotest

Новая функция SetGlobalRandom настраивает глобальный, детерминированный источник криптографической случайности на время теста. Она влияет на crypto/rand и все неявные источники криптографической случайности в пакетах crypto/....

time

Настройка GODEBUG asynctimerchan, введённая в Go 1.23, будет удалена в следующем мажорном выпуске Go. Начиная с Go 1.27, пакет time всегда будет использовать небуферизированные (синхронные) каналы для таймеров, независимо от настройки GODEBUG или версии языка в go.mod.


Читайте также: