Примечания к выпуску Go 1.25

Введение в Go 1.25

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

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

В языке нет изменений, влияющих на программы на Go в версии 1.25. Однако, в спецификации языка понятие «core types» было удалено в пользу более подробного текста. См. соответствующую запись в блоге для получения дополнительной информации.

Инструменты

Команда go

Опция go build -asan теперь по умолчанию выполняет проверку утечек памяти при завершении программы. Это приведет к выводу ошибки, если память, выделенная C, не освобождена и не ссылается ни на какую другую память, выделенную либо C, либо Go. Эти новые сообщения об ошибках могут быть отключены установкой ASAN_OPTIONS=detect_leaks=0 в окружении при запуске программы.

Дистрибутив Go будет содержать меньше предварительно скомпилированных исполняемых файлов инструментов. Основные двоичные файлы инструментария, такие как компилятор и линкер, по-прежнему будут включены, но инструменты, которые не вызываются операциями сборки или тестирования, будут собираться и запускаться по мере необходимости через go tool.

Новая директива ignore в go.mod может быть использована для указания каталогов, которые команда go должна игнорировать. Файлы в этих каталогах и их подкаталогах будут проигнорированы командой go при сопоставлении паттернов пакетов, таких как all или ./..., но по-прежнему будут включены в zip-файлы модулей.

Новая опция go doc -http запустит сервер документации, показывающий документацию для запрашиваемого объекта, и откроет документацию в окне браузера.

Новая опция go version -m -json выводит JSON-кодирование структур runtime/debug.BuildInfo, встроенных в указанные двоичные файлы Go.

Команда go теперь поддерживает использование подкаталога репозитория в качестве пути корня модуля при разрешении пути модуля с использованием синтаксиса <meta name="go-import" content="root-path vcs repo-url subdir">, чтобы указать, что root-path соответствует subdir репозитория repo-url с системой управления версиями vcs.

Новый шаблон пакетов work соответствует всем пакетам в рабочем (ранее называвшемся main) модуле: либо единичному рабочему модулю в режиме модуля, либо набору модулей рабочей среды в режиме рабочей среды.

Когда команда go обновляет строку go в файле go.mod или go.work, она больше не добавляет строку toolchain, указывающую текущую версию команды.

Vet

Команда go vet включает новые анализаторы:

  • hostport, который сообщает об использовании fmt.Sprintf("%s:%d", host, port) для построения адресов для net.Dial, так как это не будет работать с IPv6; вместо этого он предлагает использовать net.JoinHostPort.

Среда выполнения

Контейнеросознательный GOMAXPROCS

Поведение GOMAXPROCS по умолчанию изменилось. В предыдущих версиях Go, GOMAXPROCS по умолчанию равен количеству логических процессоров, доступных при запуске (runtime.NumCPU). Go 1.25 вводит два изменения:

  1. В Linux среда выполнения учитывает ограничение пропускной способности CPU группы контроля (cgroup), содержащей процесс, если таковая имеется. Если ограничение пропускной способности CPU ниже, чем количество доступных логических процессоров, GOMAXPROCS будет по умолчанию установлено на меньшее ограничение. В системах контейнеризации, таких как Kubernetes, ограничения пропускной способности CPU cgroup обычно соответствуют параметру «CPU limit». Среда выполнения Go не учитывает параметр «CPU requests».

  2. На всех операционных системах среда выполнения периодически обновляет GOMAXPROCS, если количество логических процессоров или ограничение пропускной способности CPU cgroup изменяется.

Оба этих поведения автоматически отключаются, если GOMAXPROCS установлен вручную через переменную окружения GOMAXPROCS или вызов runtime.GOMAXPROCS. Их также можно отключить явно с помощью настроек GODEBUG containermaxprocs=0 и updatemaxprocs=0 соответственно.

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

Новый экспериментальный сборщик мусора

Новый сборщик мусора теперь доступен в экспериментальном режиме. Дизайн этого сборщика улучшает производительность маркировки и сканирования маленьких объектов благодаря лучшей локальности и масштабируемости CPU. Результаты бенчмарков различаются, но мы ожидаем снижение накладных расходов на сборку мусора на 10–40% в реальных программах, которые активно используют сборщик мусора.

Новый сборщик мусора может быть включён установкой GOEXPERIMENT=greenteagc во время сборки. Мы ожидаем, что дизайн продолжит развиваться и улучшаться. Поэтому мы приглашаем разработчиков Go опробовать его и сообщить о своём опыте. См. issue на GitHub для получения дополнительных сведений о дизайне и инструкций по предоставлению обратной связи.

Трассировка в стиле flight recorder

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

Новый API runtime/trace.FlightRecorder предоставляет лёгкий способ захватить трассировку выполнения среды выполнения, непрерывно записывая трассировку в кольцевой буфер в памяти. Когда происходит значимое событие, программа может вызвать FlightRecorder.WriteTo, чтобы сделать снимок последних нескольких секунд трассировки в файл. Этот подход создаёт гораздо меньшую трассировку, позволяя приложениям захватывать только те трассировки, которые важны.

Длительность и объём данных, записываемых FlightRecorder, могут быть настроены с помощью FlightRecorderConfig.

Изменение вывода необработанного панического состояния

Сообщение, выводимое при завершении программы из-за необработанного панического состояния, которое было восстановлено и повторно вызвано, больше не повторяет текст значения паники.

Ранее, если программа вызвала панику с panic("PANIC"), восстановила панику и затем снова вызвала панику с исходным значением, то выводилось:

<code>panic: PANIC [recovered]
panic: PANIC
</code>

Эта программа теперь выведет:

<code>panic: PANIC [recovered, repanicked]
</code>

Имена VMA в Linux

В системах Linux с поддержкой ядром анонимных областей виртуальной памяти (VMA) (CONFIG_ANON_VMA_NAME), среда выполнения Go будет аннотировать анонимные области памяти, указывая их назначение. Например, [anon: Go: heap] для кучной памяти. Это поведение может быть отключено с помощью настройки GODEBUG decoratemappings=0.

Компилятор

nil pointer bug

В этом релизе исправлена ошибка компилятора, появившаяся в Go 1.21, которая могла некорректно откладывать проверку указателя на nil. Программы, подобные следующей, которые раньше успешно выполнялись (неправильно), теперь (правильно) будут паниковать с ошибкой nil-pointer:

<code>package main

import "os"

func main() {
  f, err := os.Open("nonExistentFile")
  name := f.Name()
  if err != nil {
    return
  }
  println(name)
}
</code>

Эта программа некорректна, потому что использует результат os.Open до проверки ошибки. Если err не равен nil, то результат f может быть nil, в этом случае вызов f.Name() должен привести к панике. Однако в версиях Go 1.21–1.24 компилятор некорректно откладывал проверку nil до после проверки ошибки, что приводило к успешному выполнению программы, нарушая спецификацию Go. В Go 1.25 такое больше не будет работать. Если изменение влияет на ваш код, то решение — поместить проверку ошибки раньше в коде, желательно сразу после инструкции, создающей ошибку.

Поддержка DWARF5

Компилятор и линкер в Go 1.25 теперь генерируют отладочную информацию с использованием DWARF версии 5. Более новая версия DWARF уменьшает объем пространства, необходимого для отладочной информации в двоичных файлах Go, а также уменьшает время линковки, особенно для больших Go-приложений. Генерацию DWARF 5 можно отключить, установив переменную окружения GOEXPERIMENT=nodwarf5 во время сборки (эта резервная опция может быть удалена в будущих версиях Go).

Быстрее срезы

Компилятор теперь может выделять хранилище для срезов на стеке в большем числе ситуаций, что повышает производительность. Это изменение может усиливать последствия некорректного использования unsafe.Pointer, см., например, issue 73199. Для выявления таких проблем можно использовать bisect tool, чтобы найти проблемное выделение, используя флаг -compile=variablemake. Все новые стековые выделения также можно отключить с помощью -gcflags=all=-d=variablemakehash=n.

Линкер

Линкер теперь принимает опцию командной строки -funcalign=N, которая указывает выравнивание точек входа функций. Значение по умолчанию зависит от платформы и не изменилось в этом релизе.

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

Новый пакет testing/synctest

Новый пакет testing/synctest предоставляет поддержку тестирования конкурентного кода.

Функция Test запускает функцию теста в изолированной «пузырьковой» среде. Внутри пузырька время виртуализовано: функции пакета time работают с фиктивными часами, и часы передвигаются мгновенно, если все горутины в пузырьке заблокированы.

Функция Wait ожидает, пока все горутины в текущем пузыре не заблокируются.

Этот пакет впервые стал доступен в Go 1.24 под GOEXPERIMENT=synctest, с немного другим API. Эксперимент теперь перешёл в общедоступную версию. Старое API всё ещё присутствует, если установлен GOEXPERIMENT=synctest, но будет удалено в Go 1.26.

Новый экспериментальный пакет encoding/json/v2

Go 1.25 включает новую экспериментальную реализацию JSON, которую можно включить, установив переменную окружения GOEXPERIMENT=jsonv2 во время сборки.

При включении двух новых пакетов становятся доступны:

  • Пакет encoding/json/v2 — это крупное обновление пакета encoding/json.
  • Пакет encoding/json/jsontext предоставляет низкоуровневую обработку синтаксиса JSON.

Кроме того, при включённом эксперименте “jsonv2”:

  • Пакет encoding/json использует новую реализацию JSON. Поведение при маршалинге и демаршалинге остаётся неизменным, но текст ошибок, возвращаемых функциями пакета, может измениться.
  • Пакет encoding/json содержит ряд новых опций, которые могут использоваться для настройки маршаллера и демаршаллера.

Новая реализация работает значительно быстрее, чем существующая, в большинстве сценариев. В целом, производительность кодирования между реализациями примерно одинакова, а декодирование работает значительно быстрее в новой реализации. См. репозиторий github.com/go-json-experiment/jsonbench для более подробного анализа.

См. пропозиционную задачу для получения дополнительных сведений.

Мы призываем пользователей пакета encoding/json протестировать свои программы с включённым GOEXPERIMENT=jsonv2, чтобы помочь выявить возможные проблемы совместимости с новой реализацией.

Мы ожидаем, что дизайн пакета encoding/json/v2 будет продолжать развиваться. Мы призываем разработчиков попробовать новый API и предоставить обратную связь в пропозиционной задаче.

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

archive/tar

Реализация Writer.AddFS теперь поддерживает символические ссылки для файловых систем, реализующих io/fs.ReadLinkFS.

encoding/asn1

Unmarshal и UnmarshalWithParams теперь более последовательно обрабатывают типы ASN.1 T61String и BMPString. Это может привести к тому, что ранее допустимые некорректные кодировки теперь будут отклоняться.

crypto

MessageSigner — это новый интерфейс подписи, который может быть реализован подписывающими объектами, желающими самостоятельно хэшировать подписываемое сообщение. Также введена новая функция SignMessage, которая пытается преобразовать интерфейс Signer в MessageSigner, используя метод MessageSigner.SignMessage, если преобразование успешно, и Signer.Sign, если нет. Это может быть полезно, когда код должен поддерживать как Signer, так и MessageSigner.

Изменение настройки fips140 GODEBUG после запуска программы теперь не производит никакого действия (no-op). Ранее это было документировано как запрещённое действие, и при изменении могло приводить к панике.

SHA-1, SHA-256 и SHA-512 теперь работают медленнее на amd64, если инструкции AVX2 недоступны. Все серверные процессоры (и большинство других), выпущенные с 2015 года, поддерживают AVX2.

crypto/ecdsa

Новые функции ParseRawPrivateKey, ParseUncompressedPublicKey, PrivateKey.Bytes и PublicKey.Bytes реализуют низкоуровневые кодировки, заменяя необходимость использовать функции и методы пакета crypto/elliptic или math/big.

При включённом режиме FIPS 140-3 подпись теперь выполняется в четыре раза быстрее, что соответствует производительности не-FIPS режима.

crypto/ed25519

При включённом режиме FIPS 140-3 подпись теперь выполняется в четыре раза быстрее, что соответствует производительности не-FIPS режима.

crypto/elliptic

Скрытые и недокументированные методы Inverse и CombinedMult в некоторых реализациях Curve были удалены.

crypto/rsa

PublicKey больше не утверждает, что значение модуля обрабатывается как секретное. VerifyPKCS1v15 и VerifyPSS уже предупреждали, что все входные данные являются публичными и могут быть раскрыты, а также существуют математические атаки, которые позволяют восстановить модуль из других публичных значений.

Генерация ключей теперь выполняется в три раза быстрее.

crypto/sha1

Хеширование теперь выполняется в два раза быстрее на amd64, если доступны инструкции SHA-NI.

crypto/sha3

Новый метод SHA3.Clone реализует hash.Cloner.

Хеширование теперь выполняется в два раза быстрее на процессорах Apple M.

crypto/tls

Новое поле ConnectionState.CurveID предоставляет информацию о механизме обмена ключами, использованном для установления соединения.

Новый обратный вызов Config.GetEncryptedClientHelloKeys может использоваться для установки EncryptedClientHelloKey для сервера при получении от клиента расширения Encrypted Client Hello.

Алгоритмы подписи SHA-1 теперь запрещены в рукопожатиях TLS 1.2 согласно RFC 9155. Их можно снова включить с помощью настройки GODEBUG tlssha1=1.

При включённом режиме FIPS 140-3 в TLS 1.2 теперь требуется Extended Master Secret, а Ed25519 и X25519MLKEM768 теперь разрешены.

Серверы TLS теперь предпочитают самую высокую поддерживаемую версию протокола, даже если это не наиболее предпочтительная версия клиента.

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

crypto/x509

CreateCertificate, CreateCertificateRequest, and CreateRevocationList теперь могут принимать crypto.MessageSigner интерфейс подписи, а также crypto.Signer. Это позволяет этим функциям использовать подписывающие интерфейсы, реализующие «одноразовые» интерфейсы подписи, где хеширование выполняется как часть операции подписи, а не вызывающей стороной.

CreateCertificate теперь использует усеченное значение SHA-256 для заполнения SubjectKeyId, если оно отсутствует. Настройка GODEBUG x509sha256skid=0 возвращает использование SHA-1.

ParseCertificate теперь отклоняет сертификаты, содержащие расширение BasicConstraints, которое содержит отрицательное значение pathLenConstraint.

ParseCertificate теперь более последовательно обрабатывает строки, закодированные с использованием типов ASN.1 T61String и BMPString. Это может привести к тому, что ранее принимавшиеся некорректные кодировки теперь будут отклоняться.

debug/elf

Пакет debug/elf добавляет две новые константы:

go/ast

Функции FilterPackage, PackageExports, и MergePackageFiles, а также тип MergeMode и его константы, все устарели, поскольку предназначены исключительно для использования с давно устаревшей механикой Object и Package.

Новая функция PreorderStack, как и Inspect, обходит синтаксическое дерево и предоставляет контроль над спуском в поддеревья, но, как удобство, также предоставляет стек содержащих узлов на каждом этапе.

go/parser

Функция ParseDir устарела.

go/token

Новый метод FileSet.AddExistingFiles позволяет добавлять существующие File в FileSet, или создавать FileSet для произвольного набора File, что устраняет проблемы, связанные с использованием единственного глобального FileSet в долгоживущих приложениях.

go/types

Var теперь имеет метод Var.Kind, который классифицирует переменную как одну из следующих: пакетная, получатель, параметр, результат, локальная переменная или поле структуры.

Новая функция LookupSelection ищет поле или метод с заданным именем и типом получателя, подобно существующей функции LookupFieldOrMethod, но возвращает результат в форме Selection.

hash

Новый интерфейс XOF может быть реализован для «функций с расширяющимся выходом», которые являются хэш-функциями с произвольной или неограниченной длиной выхода, такими как SHAKE.

Хэши, реализующие новый интерфейс Cloner, могут возвращать копию своего состояния. Все стандартные реализации Hash в стандартной библиотеке теперь реализуют Cloner.

hash/maphash

Новый метод Hash.Clone реализует hash.Cloner.

io/fs

Новый интерфейс ReadLinkFS предоставляет возможность чтения символических ссылок в файловой системе.

log/slog

GroupAttrs создаёт группу Attr из среза значений Attr.

Record теперь имеет метод Source, возвращающий информацию о месте происхождения записи или nil, если такая информация недоступна.

mime/multipart

Новая вспомогательная функция FileContentDisposition формирует заголовки Content-Disposition в формате multipart.

net

LookupMX и Resolver.LookupMX теперь возвращают DNS-имена, которые выглядят как действительные IP-адреса, а также корректные доменные имена. Ранее, если сервер имён возвращал IP-адрес в виде DNS-имени, LookupMX отбрасывал его, как того требуют RFC. Однако на практике серверы имён иногда возвращают IP-адреса.

В Windows, ListenMulticastUDP теперь поддерживает IPv6-адреса.

В Windows теперь возможна конвертация между os.File и сетевым соединением. В частности, функции FileConn, FilePacketConn и FileListener теперь реализованы и возвращают сетевое соединение или слушатель, соответствующий открытому файлу. Аналогично, методы File типов TCPConn, UDPConn, UnixConn, IPConn, TCPListener и UnixListener теперь реализованы и возвращают базовый os.File сетевого соединения.

net/http

Новый CrossOriginProtection реализует защиту от межсайтовой подделки запросов (CSRF) путём отклонения небезопасных межсайтовых запросов браузера. Он использует современные метаданные Fetch браузера, не требует токенов или cookies и поддерживает обходы на основе источника и шаблона.

os

В Windows NewFile теперь поддерживает дескрипторы, открытые для асинхронного ввода-вывода (то есть, syscall.FILE_FLAG_OVERLAPPED указан в вызове syscall.CreateFile). Эти дескрипторы связаны с портом завершения ввода-вывода среды выполнения Go, что обеспечивает следующие преимущества для результирующего File:

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

Обратите внимание, что дескриптор может быть связан только с одним портом завершения ввода-вывода одновременно. Если дескриптор, переданный в NewFile, уже связан с портом завершения ввода-вывода, возвращённый File переходит в режим синхронного ввода-вывода. В этом случае методы ввода-вывода блокируют поток операционной системы, а методы установки сроков действия не работают.

Файловые системы, возвращаемые DirFS и Root.FS, реализуют новый интерфейс io/fs.ReadLinkFS. CopyFS поддерживает символические ссылки при копировании файловых систем, реализующих io/fs.ReadLinkFS.

Тип Root поддерживает следующие дополнительные методы:

reflect

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

regexp/syntax

Синтаксисы классов символов \p{name} и \P{name} теперь принимают имена Any, ASCII, Assigned, Cn и LC, а также псевдонимы категорий Юникода, такие как \p{Letter} для \pL. Следуя Unicode TR18, они теперь также используют поиск имён без учёта регистра, игнорируя пробелы, подчёркивания и дефисы.

runtime

Функции очистки, запланированные с помощью AddCleanup, теперь выполняются одновременно и параллельно, что делает очистку более пригодной для интенсивного использования, например, в пакете unique. Следует отметить, что отдельные функции очистки всё ещё должны передавать свою работу в новую горутину, если они должны выполняться или блокироваться на длительное время, чтобы избежать блокировки очереди очистки.

Новая настройка GODEBUG=checkfinalizers=1 помогает находить типичные проблемы с финализаторами и функциями очистки, такие как описанные в руководстве по сборке мусора. В этом режиме среда выполнения запускает диагностику на каждой итерации сборки мусора и также регулярно выводит длину очередей финализаторов и очистки в stderr, чтобы помочь выявить проблемы с долгоживущими финализаторами и/или функциями очистки. См. документацию по GODEBUG для получения дополнительных сведений.

Новая функция SetDefaultGOMAXPROCS устанавливает значение GOMAXPROCS в значение по умолчанию для среды выполнения, как если бы переменная окружения GOMAXPROCS не была установлена. Это полезно для включения нового значения по умолчанию для GOMAXPROCS, если оно было отключено переменной окружения GOMAXPROCS или предыдущим вызовом GOMAXPROCS.

runtime/pprof

Профиль мьютекса для конкуренции на внутренних блокировках среды выполнения теперь корректно указывает на конец критической секции, которая вызвала задержку. Это соответствует поведению профиля при конкуренции на значениях sync.Mutex. Настройка runtimecontentionstacks для GODEBUG, которая позволяла выбрать необычное поведение Go версии 1.22–1.24 для этой части профиля, теперь удалена.

sync

Новый метод WaitGroup.Go делает обычный паттерн создания и подсчёта горутин более удобным.

testing

Новые методы T.Attr, B.Attr и F.Attr выводят атрибут в лог теста. Атрибут — это произвольная пара ключ-значение, связанная с тестом.

Например, в тесте с именем TestF, t.Attr("key", "value") выводит:

<code>=== ATTR  TestF key value
</code>

С флагом -json атрибуты появляются как новое действие “attr”.

Новый метод Output для T, B и F предоставляет io.Writer, записывающий в тот же поток вывода теста, что и TB.Log. Как и TB.Log, вывод отступается, но не включает номер файла и строки.

Функция AllocsPerRun теперь вызывает панику, если выполняются параллельные тесты. Результат AllocsPerRun является нестабильным, если выполняются другие тесты. Новое поведение с паникой помогает выявить такие ошибки.

testing/fstest

MapFS реализует новый интерфейс io/fs.ReadLinkFS. TestFS проверит функциональность интерфейса io/fs.ReadLinkFS, если он реализован. TestFS больше не будет следовать по символическим ссылкам, чтобы избежать неограниченной рекурсии.

unicode

Новая карта CategoryAliases обеспечивает доступ к псевдонимам категорий, таким как «Letter» для «L».

Новые категории Cn и LC определяют неприсвоенные кодовые точки и буквы с учетом регистра соответственно. Эти категории всегда были определены в Unicode, но случайно были опущены в предыдущих версиях Go. Категория C теперь включает Cn, что означает, что она теперь включает все неприсвоенные кодовые точки.

unique

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

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

Порты

Darwin

Как было объявлено в примечаниях к выпуску Go 1.24, Go 1.25 требует macOS 12 Monterey или более поздней версии. Поддержка предыдущих версий была прекращена.

Windows

Go 1.25 — это последний выпуск, который содержит испорченный 32-битный порт windows/arm (GOOS=windows GOARCH=arm). Он будет удален в Go 1.26.

AMD64

В режиме GOAMD64=v3 или выше компилятор теперь будет использовать инструкции fused multiply-add, чтобы сделать арифметику с плавающей точкой быстрее и точнее. Это может изменить точные значения с плавающей точкой, которые генерирует программа.

Чтобы избежать объединения, используйте явное приведение к float64, например float64(a*b)+c.

Loong64

Для поддержки Loong64 были приняты следующие предложения:

GoRu.dev Golang на русском

На сайте представлена адаптированная под русский язык документация языка программирования Golang