Примечания к выпуску Go 1.21
Введение в Go 1.21
Последний выпуск Go, версия 1.21, появился через шесть месяцев после Go 1.20. Большинство изменений касаются реализации инструментария, среды выполнения и библиотек. Как и всегда, выпуск сохраняет обещание совместимости Go 1; на самом деле, Go 1.21 улучшает это обещание. Ожидается, что почти все программы на Go будут продолжать компилироваться и выполняться так же, как и раньше.
В Go 1.21 вводится небольшое изменение в нумерации выпусков.
Ранее мы использовали Go 1.N для обозначения как общей версии языка Go, так и семейства выпусков,
а также первого выпуска в этом семействе.
Начиная с Go 1.21, первый выпуск теперь называется Go 1.N.0.
Сегодня мы выпускаем как язык Go 1.21, так и его первоначальную реализацию — выпуск Go 1.21.0.
Эти примечания относятся к «Go 1.21»; инструменты, такие как go version, будут сообщать «go1.21.0»
(пока вы не обновитесь до Go 1.21.1).
См. «Версии Go» в документации «Go Toolchains» для получения подробной информации
о новой схеме нумерации версий.
Изменения в языке
В Go 1.21 добавлены три новых встроенных функции.
-
Новые функции
minиmaxвычисляют наименьшее (или наибольшее, дляmax) значение из заданного фиксированного числа аргументов. См. спецификацию языка для подробностей. -
Новая функция
clearудаляет все элементы из карты или обнуляет все элементы среза. См. спецификацию языка для подробностей.
Порядок инициализации пакетов теперь задан более точно. Новый алгоритм следующий:
- Отсортировать все пакеты по пути импорта.
- Повторять, пока список пакетов не будет пуст:
- Найти первый пакет в списке, для которого все импорты уже инициализированы.
- Инициализировать этот пакет и удалить его из списка.
Это может изменить поведение некоторых программ, которые полагались на определенный порядок инициализации, который не выражался явными импортами. Поведение таких программ в предыдущих выпусках не было чётко определено. Новое правило обеспечивает однозначное определение.
Были внесены несколько улучшений, повышающих мощность и точность вывода типов.
- (Частично инстанцированная) дженерик-функция теперь может быть вызвана с аргументами, которые сами являются (частично инстанцированными) дженерик-функциями. Компилятор будет пытаться вывести недостающие аргументы типа вызываемой функции (как и раньше), а также, для каждого аргумента, являющегося дженерик-функцией, которая не полностью инстанцирована, — её недостающие аргументы типа (новое). Типичные случаи использования — вызовы дженерик-функций, работающих с контейнерами (например, slices.IndexFunc), где аргумент функции также может быть дженерик-функцией, и где аргумент типа вызываемой функции и её аргументов выводится из типа контейнера. В более общем случае, дженерик-функция теперь может использоваться без явной инстанциации, если она присваивается переменной или возвращается как результат, если аргументы типа могут быть выведены из присваивания.
- Вывод типов теперь также учитывает методы, когда значение присваивается интерфейсу: аргументы типа для параметров типа, используемых в сигнатурах методов, могут быть выведены из соответствующих типов параметров совпадающих методов.
- Аналогично, поскольку аргумент типа должен реализовывать все методы своего соответствующего ограничения, методы аргумента типа и ограничения сопоставляются, что может привести к выводу дополнительных аргументов типа.
- Если передаются несколько неявно типизированных константных аргументов разных типов (например, неявно типизированное целое и неявно типизированная числовая константа), в параметры с тем же (не иным образом указанным) типом параметра, вместо ошибки, теперь вывод типов определяет тип с тем же подходом, что и оператор с неявно типизированными константными операндами. Это изменение приводит типы, выводимые из неявно типизированных константных аргументов, в соответствие с типами константных выражений.
- Вывод типов теперь точен при сопоставлении соответствующих типов в присваиваниях: компонентные типы (например, элементы срезов или типы параметров в сигнатурах функций) должны быть идентичны (при подходящих аргументах типа), чтобы соответствовать, иначе вывод неудачен. Это изменение приводит к более точным сообщениям об ошибках: где раньше вывод типов мог ошибочно завершиться успешно и привести к недопустимому присваиванию, компилятор теперь сообщает об ошибке вывода, если два типа не могут совпадать.
В более общем виде, описание вывода типов в спецификации языка было уточнено. Вместе все эти изменения делают вывод типов более мощным, а ошибки вывода — менее неожиданными.
Go 1.21 включает предварительную реализацию языкового изменения, которое мы рассматриваем для будущих версий Go: сделать переменные цикла for пер-итерацией, а не пер-циклом, чтобы избежать случайных ошибок с совместным использованием. Для получения подробной информации о том, как попробовать это языковое изменение, см. страницу вики LoopvarExperiment.
Go 1.21 теперь определяет, что если горутина находится в состоянии panic и recover был вызван напрямую
defer-функцией, возвращаемое значение recover гарантированно не будет nil. Чтобы обеспечить это, вызов panic
с nil интерфейсным значением (или не типизированным nil) приводит к ошибке среды выполнения типа
*runtime.PanicNilError.
Для поддержки программ, написанных для более ранних версий Go, можно включить обратно nil panic, установив
GODEBUG=panicnil=1.
Эта настройка включается автоматически при компиляции программы, чей основной пакет находится в модуле,
объявляющем go 1.20 или более раннюю версию.
Инструменты
Go 1.21 добавляет улучшенную поддержку обратной и прямой совместимости в инструментарии Go.
Для улучшения обратной совместимости, Go 1.21 формализует
использование переменной окружения GODEBUG для управления
поведением по умолчанию для изменений, которые не нарушают совместимость согласно
политике совместимости,
но тем не менее могут привести к поломке существующих программ.
(Например, программы, зависящие от багов, могут сломаться
при исправлении этих багов, но исправления багов не считаются разрушающими изменениями.)
Когда Go должен сделать такое изменение поведения,
он теперь выбирает между старым и новым поведением на основе
строки go в файле go.work рабочей области
или файла go.mod основного модуля.
Обновление до новой версии инструментария Go, но оставление строки go
установленной на оригинальную (более старую) версию Go сохраняет поведение старого
инструментария.
С этой поддержкой совместимости, последняя версия инструментария Go всегда
должна быть лучшей, самой безопасной реализацией более старой версии Go.
См. «Go, обратная совместимость и GODEBUG» для подробностей.
Для улучшения прямой совместимости, Go 1.21 теперь читает строку go
в файле go.work или go.mod как строгое минимальное требование: go 1.21.0 означает,
что рабочая область или модуль нельзя использовать с Go 1.20 или с Go 1.21rc1.
Это позволяет проектам, зависящим от исправлений, сделанных в более поздних версиях Go,
обеспечить, что они не будут использоваться с более ранними версиями.
Это также даёт лучшую систему сообщений об ошибках для проектов, использующих новые возможности Go:
когда проблема в том, что нужна более новая версия Go,
эта проблема сообщается явно, а не пытается собрать код
и выводит ошибки о неразрешённых импортах или синтаксических ошибках.
Чтобы сделать эти новые более строгие требования к версиям проще в управлении,
команда go теперь может запускать не только инструментарий,
встроенный в её собственное релиз, но и другие версии инструментария Go, найденные в PATH
или загруженные по требованию.
Если строка go в файле go.mod или go.work
объявляет минимальное требование к более новой версии Go, команда go
автоматически найдёт и запустит эту версию.
Новый директивный элемент toolchain задаёт рекомендуемую минимальную версию инструментария для использования,
которая может быть новее, чем строгое минимальное значение go.
См. «Go Toolchains» для подробностей.
Команда go
Флаг сборки -pgo теперь по умолчанию равен -pgo=auto,
а ограничение на указание одного основного пакета в командной строке теперь удалено. Если в директории основного пакета присутствует файл с именем default.pgo, команда go будет использовать его для включения профайлинг-ориентированной оптимизации при сборке соответствующей программы.
Флаг -C dir теперь должен быть первым флагом в командной строке при его использовании.
Новая опция go test
-fullpath выводит полные пути в сообщениях журнала тестов,
а не только базовые имена.
Флаг go test -c теперь
поддерживает запись тестовых бинарных файлов для нескольких пакетов, каждый в
pkg.test, где pkg — имя пакета.
Ошибка возникает, если более чем один тестируемый пакет, компилируемый в данный момент, имеет одно и то же имя пакета.
Флаг go test -o теперь
принимает аргумент директории; в этом случае тестовые бинарные файлы записываются в указанную директорию вместо текущей.
При использовании внешнего (C) компоновщика с включённым cgo, пакет runtime/cgo теперь передаётся в компоновщик Go как дополнительная зависимость, чтобы обеспечить совместимость среды выполнения Go с любыми дополнительными библиотеками, добавленными компоновщиком C.
Cgo
В файлах, где используется import "C", средство сборки Go теперь
корректно сообщает об ошибках при попытке объявить Go-методы для C-типов.
Среда выполнения
При печати очень глубоких стеков, среда выполнения теперь выводит первые 50 (внутренних) фреймов, за которыми следуют последние 50 (внешних) фреймов, вместо того чтобы просто выводить первые 100 фреймов. Это делает проще понять, насколько глубоко начались рекурсивные стеки, и особенно полезно при отладке переполнений стека.
На платформах Linux, поддерживающих прозрачные большие страницы, среда выполнения Go
теперь более явно управляет тем, какие части кучи могут быть реализованы с помощью больших страниц.
Это приводит к лучшему использованию памяти: небольшие кучи должны использовать меньше памяти (до 50% в патологических случаях), а большие кучи должны иметь меньше сломанных больших страниц в плотных частях кучи, что улучшает использование CPU и задержки до 1%. В результате этого изменения среда выполнения больше не пытается обойти определённую проблемную настройку конфигурации Linux, что может привести к более высокому расходу памяти. Рекомендуется скорректировать настройки больших страниц ОС согласно руководству по GC.
Однако доступны и другие обходные решения. См. раздел о
max_ptes_none.
В результате настройки внутренней сборки мусора среда выполнения, приложения могут увидеть снижение хвостовой задержки до 40% и небольшое уменьшение использования памяти. Некоторые приложения также могут наблюдать небольшое падение пропускной способности.
Снижение использования памяти должно быть пропорционально падению
пропускной способности, так что прежний баланс пропускной способности/памяти
может быть восстановлен (с минимальным изменением задержки) путём
увеличения GOGC и/или GOMEMLIMIT немного.
Вызовы из C в Go на потоках, созданных в C, требуют некоторой настройки для подготовки к выполнению Go. На платформах Unix эта настройка теперь сохраняется между несколькими вызовами из одного и того же потока. Это значительно снижает накладные расходы последующих вызовов из C в Go с ~1-3 микросекунд на вызов до ~100-200 наносекунд на вызов.
Компилятор
Профайлинг-ориентированная оптимизация (PGO), добавленная как предварительная возможность в Go 1.20, теперь готова к общему использованию. PGO включает дополнительные оптимизации в коде, определённом как горячий по профилям рабочих нагрузок в продакшене. Как упоминалось в разделе команды go, PGO включена по умолчанию для бинарных файлов, содержащих профиль default.pgo в директории основного пакета. Улучшения производительности зависят от поведения приложения, большинство программ из репрезентативного набора программ на Go показывают улучшение от 2 до 7% при включении PGO. См. руководство пользователя по PGO для подробной документации.
Построение с использованием PGO теперь может устранять виртуализацию некоторых вызовов методов интерфейса, добавляя конкретный вызов к наиболее часто используемому получателю. Это позволяет дальнейшую оптимизацию, например, встраивание вызываемой функции.
Go 1.21 ускоряет сборку до 6%, в основном благодаря тому, что компилятор теперь собирается с использованием PGO.
Ассемблер
В amd64 функции ассемблера без фрейма (frameless nosplit) больше не помечаются автоматически как NOFRAME.
Вместо этого атрибут NOFRAME должен быть указан явно, если это требуется,
что уже является поведением на других архитектурах, поддерживающих указатели фреймов.
Благодаря этому среда выполнения теперь сохраняет указатели фреймов при переходах стека.
Верификатор, проверяющий некорректное использование R15 при динамической линковке на amd64, был улучшен.
Линкер
В Windows/amd64 линкер (с поддержкой компилятора) теперь по умолчанию генерирует данные разворачивания SEH, что улучшает интеграцию Go-приложений с отладчиками и другими инструментами Windows.
В Go 1.21 линкер (с поддержкой компилятора) теперь способен удалять мертвые (недоступные) глобальные переменные карты, если количество записей в инициализаторе переменной достаточно велико, и если выражения инициализации не имеют побочных эффектов.
Стандартная библиотека
Новый пакет log/slog
Новый пакет log/slog предоставляет структурированное логирование с уровнями. Структурированное логирование выводит пары ключ-значение, что позволяет быстро и точно обрабатывать большие объемы логических данных. Пакет поддерживает интеграцию с популярными инструментами и сервисами анализа логов.
Новый пакет testing/slogtest
Новый пакет testing/slogtest может помочь проверить реализации slog.Handler.
Новый пакет slices
Новый пакет slices предоставляет множество общих операций над срезами, используя дженерик-функции, которые работают со срезами любого типа элемента.
Новый пакет maps
Новый пакет maps предоставляет несколько общих операций над картами, используя дженерик-функции, которые работают с картами любого типа ключа или элемента.
Новый пакет cmp
Новый пакет cmp определяет ограничение типа
Ordered и
две новые дженерик-функции
Less
и Compare, которые полезны при работе с
упорядоченными типами.
Мелкие изменения в библиотеке
Как и всегда, в библиотеке были внесены различные мелкие изменения и обновления, осуществленные с учетом обещания совместимости Go 1. Также были реализованы различные улучшения производительности, которые не перечислены здесь.
archive/tar
Реализация интерфейса
io/fs.FileInfo,
возвращаемого функцией
Header.FileInfo,
теперь реализует метод String, который вызывает
io/fs.FormatFileInfo.
archive/zip
Реализация интерфейса
io/fs.FileInfo,
возвращаемого функцией
FileHeader.FileInfo,
теперь реализует метод String, который вызывает
io/fs.FormatFileInfo.
Реализация интерфейса
io/fs.DirEntry,
возвращаемого методом
io/fs.ReadDirFile.ReadDir
типа
io/fs.File,
возвращаемого функцией
Reader.Open,
теперь реализует метод String, который вызывает
io/fs.FormatDirEntry.
bytes
Тип Buffer имеет два новых метода:
Available
и AvailableBuffer.
Эти методы могут использоваться совместно с методом
Write
для прямой записи в Buffer.
context
Новая функция WithoutCancel
возвращает копию контекста, которая не отменяется при отмене исходного контекста.
Новые функции WithDeadlineCause
и WithTimeoutCause
обеспечивают возможность установки причины отмены контекста при наступлении дедлайна или истечении таймера.
Причина может быть получена с помощью функции
Cause.
Новая функция AfterFunc
регистрирует функцию для выполнения после отмены контекста.
Оптимизация означает, что результаты вызова функций
Background
и TODO
и их преобразования в общий тип могут считаться равными.
В предыдущих версиях они всегда были разными. Сравнение значений
Context
для равенства никогда не было строго определено, поэтому это не считается несовместимым изменением.
crypto/ecdsa
PublicKey.Equal и
PrivateKey.Equal
теперь выполняются за постоянное время.
crypto/elliptic
Все методы типа Curve устарели, а также функции
GenerateKey,
Marshal и
Unmarshal.
Для операций ECDH следует использовать новый пакет crypto/ecdh.
Для более низкоуровневых операций рекомендуется использовать сторонние модули, такие как filippo.io/nistec.
crypto/rand
Пакет crypto/rand теперь использует системный вызов getrandom в NetBSD 10.0 и более поздних версиях.
crypto/rsa
Производительность частных операций в RSA (расшифровка и подпись) теперь лучше, чем в Go 1.19, для GOARCH=amd64 и GOARCH=arm64. Ранее она ухудшилась в Go 1.20.
Из-за добавления приватных полей в PrecomputedValues, PrivateKey.Precompute должен вызываться для достижения оптимальной производительности даже в случае десериализации (например, из JSON) ранее предварительно вычисленного закрытого ключа.
PublicKey.Equal и
PrivateKey.Equal
теперь выполняются за постоянное время.
Функция GenerateMultiPrimeKey и поле PrecomputedValues.CRTValues устарели. Поле PrecomputedValues.CRTValues по-прежнему будет заполняться при вызове PrivateKey.Precompute, но значения не будут использоваться во время операций расшифровки.
crypto/sha256
Операции SHA-224 и SHA-256 теперь используют нативные инструкции, если они доступны, когда GOARCH=amd64, что обеспечивает прирост производительности примерно в 3–4 раза.
crypto/tls
Серверы теперь пропускают проверку клиентских сертификатов (включая не выполнение
Config.VerifyPeerCertificate)
для возобновлённых соединений, кроме проверки срока действия. Это делает тикеты сессий больше, если используются клиентские сертификаты. Клиенты уже пропускали проверку при возобновлении, но теперь они также проверяют срок действия, даже если установлен параметр Config.InsecureSkipVerify.
Теперь приложения могут управлять содержимым тикетов сессий.
- Новый тип
SessionStateописывает возобновляемую сессию. - Метод
SessionState.Bytesи функцияParseSessionStateсериализуют и десериализуютSessionState. - Хуки
Config.WrapSessionиConfig.UnwrapSessionконвертируютSessionStateв тикет и обратно на стороне сервера. - Методы
Config.EncryptTicketиConfig.DecryptTicketобеспечивают реализацию по умолчанию дляWrapSessionиUnwrapSession. - Метод
ClientSessionState.ResumptionStateи функцияNewResumptionStateмогут использоваться реализациейClientSessionCacheдля сохранения и возобновления сессий на стороне клиента.
Чтобы уменьшить потенциал использования билетов сессий в качестве механизма отслеживания между соединениями, сервер теперь выдает новые билеты при каждом возобновлении (если они поддерживаются и не отключены), и билеты больше не содержат идентификатор ключа, которым они были зашифрованы. При передаче большого количества ключей в Conn.SetSessionTicketKeys это может привести к заметному снижению производительности.
Как клиенты, так и серверы теперь реализуют расширение Extended Master Secret (RFC 7627). Устаревшее использование ConnectionState.TLSUnique было отменено, и теперь оно устанавливается для возобновленных соединений, поддерживающих Extended Master Secret.
Новый тип QUICConn предоставляет поддержку реализаций QUIC, включая поддержку 0-RTT. Следует отметить, что это сама по себе не реализация QUIC, и поддержка 0-RTT все еще не доступна в TLS.
Новая функция VersionName возвращает имя для номера версии TLS.
Коды оповещений TLS, отправляемые сервером при неудачной аутентификации клиента, были улучшены. Ранее такие неудачи всегда приводили к оповещению «bad certificate». Теперь определенные сценарии неудач будут приводить к более подходящим кодам оповещений, согласно RFC 5246 и RFC 8446:
- Для соединений TLS 1.3, если сервер настроен на требование аутентификации клиента с использованием RequireAnyClientCert или RequireAndVerifyClientCert, и клиент не предоставляет сертификат, сервер теперь вернет оповещение «certificate required».
- Если клиент предоставляет сертификат, который не подписан набором доверенных центров сертификации, настроенных на сервере, сервер вернет оповещение «unknown certificate authority».
- Если клиент предоставляет сертификат, который либо истек, либо еще не действителен, сервер вернет оповещение «expired certificate».
- Во всех остальных сценариях, связанных с неудачами аутентификации клиента, сервер по-прежнему возвращает «bad certificate».
crypto/x509
RevocationList.RevokedCertificates устарел и заменен новым полем RevokedCertificateEntries, которое представляет собой срез RevocationListEntry. RevocationListEntry содержит все поля из pkix.RevokedCertificate, а также код причины отзыва.
Ограничения имен теперь корректно применяются к сертификатам, не являющимся листовыми (non-leaf), и не применяются к тем сертификатам, где они выражены.
debug/elf
Новый метод File.DynValue может использоваться для получения числовых значений, перечисленных с заданным динамическим тегом.
Постоянные флаги, разрешенные в динамическом теге DT_FLAGS_1, теперь определены с типом DynFlag1. Эти теги имеют имена, начинающиеся с DF_1.
Пакет теперь определяет константу
COMPRESS_ZSTD.
Пакет теперь определяет константу
R_PPC64_REL24_P9NOTOC.
debug/pe
Попытки чтения из секции, содержащей неинициализированные данные,
с использованием
Section.Data
или читателя, возвращённого функцией Section.Open
теперь возвращают ошибку.
embed
io/fs.File,
возвращённый функцией
FS.Open, теперь
имеет метод ReadAt, который реализует
io.ReaderAt.
Вызов FS.Open.Stat
возвращает тип, который теперь реализует метод String,
вызывающий
io/fs.FormatFileInfo.
encoding/binary
Новая переменная
NativeEndian
может использоваться для преобразования между срезами байт и целыми числами
с использованием native endianness текущей машины.
errors
Новая ошибка
ErrUnsupported
предоставляет стандартизированный способ указания, что запрашиваемая
операция не может быть выполнена, поскольку она не поддерживается.
Например, вызов
os.Link при использовании
файловой системы, которая не поддерживает жёсткие ссылки.
flag
Новая функция BoolFunc
и метод
FlagSet.BoolFunc
определяют флаг, который не требует аргумента и вызывает
функцию при использовании флага. Это похоже на
Func, но для
булевого флага.
Определение флага
(через Bool,
BoolVar,
Int,
IntVar и т. д.)
вызывает панику, если Set
уже была вызвана для флага с тем же именем. Это изменение
предназначено для обнаружения случаев, когда изменения
порядка инициализации приводят к тому, что операции с флагами
выполняются в другом порядке, чем ожидалось. Во многих случаях решение
этой проблемы заключается в том, чтобы добавить явную зависимость пакета,
чтобы правильно упорядочить определение перед любыми
Set операциями.
go/ast
Новое предикатное выражение IsGenerated
сообщает, содержит ли синтаксическое дерево файла специальный комментарий,
которыйConventionally указывает, что файл был сгенерирован инструментом.
Новое поле
File.GoVersion
записывает минимальную версию Go, необходимую для
любых директив //go:build или // +build.
go/build
Пакет теперь разбирает директивы сборки (комментарии, начинающиеся с
//go:), находящиеся в заголовке файла (до объявления
package). Эти директивы доступны в новых полях
Package:
Directives,
TestDirectives,
и
XTestDirectives.
go/build/constraint
Новая функция
GoVersion
возвращает минимальную версию Go, implied (подразумеваемую) выражением сборки.
go/token
Новый метод
File.Lines
возвращает таблицу номеров строк файла в том же формате, который принимает
File.SetLines.
go/types
Новый метод
Package.GoVersion
возвращает версию языка Go, использованную для проверки пакета.
hash/maphash
Пакет hash/maphash теперь имеет реализацию на чистом Go, выбираемую с помощью тега сборки purego.
html/template
Новая ошибка
ErrJSTemplate
возвращается, когда действие появляется в литерале шаблона JavaScript.
Ранее возвращалась неэкспортируемая ошибка.
io/fs
Новая функция
FormatFileInfo
возвращает отформатированную версию
FileInfo.
Новая функция
FormatDirEntry
возвращает отформатированную версию
DirEntry.
Реализация
DirEntry,
возвращаемая функцией
ReadDir, теперь
реализует метод String, вызывающий
FormatDirEntry,
и то же самое справедливо для
значения DirEntry,
передаваемого в
WalkDirFunc.
math/big
Новый метод
Int.Float64
возвращает ближайшее значение с плавающей точкой к многоточечному целому числу,
а также указание о любых округлениях, которые произошли.
net
В Linux пакет net теперь может использовать
Multipath TCP, если ядро его поддерживает. По умолчанию это не используется.
Чтобы использовать Multipath TCP при наличии на клиенте, вызовите
метод
Dialer.SetMultipathTCP
до вызова методов
Dialer.Dial или
Dialer.DialContext.
Чтобы использовать Multipath TCP при наличии на сервере, вызовите
метод
ListenConfig.SetMultipathTCP
до вызова метода
ListenConfig.Listen.
Укажите сеть как "tcp", "tcp4" или "tcp6", как обычно.
Если Multipath TCP не поддерживается ядром или удалённым хостом,
подключение будет автоматически переключаться на TCP. Чтобы проверить,
используется ли Multipath TCP для конкретного подключения, используйте
метод
TCPConn.MultipathTCP.
В будущем выпуске Go мы можем включить Multipath TCP по умолчанию на системах, которые его поддерживают.
net/http
Новый метод ResponseController.EnableFullDuplex
позволяет обработчикам сервера одновременно читать тело HTTP/1 запроса, пока происходит запись ответа. Обычно HTTP/1 сервер автоматически потребляет оставшееся тело запроса перед началом записи ответа, чтобы избежать взаимоблокировки клиентов, которые пытаются записать полный запрос до того, как прочитают ответ. Метод EnableFullDuplex отключает такое поведение.
Новая ошибка ErrSchemeMismatch возвращается Client и Transport, когда сервер отвечает на HTTPS запрос HTTP ответом.
Пакет net/http теперь поддерживает
errors.ErrUnsupported,
в том числе выражение
errors.Is(http.ErrNotSupported, errors.ErrUnsupported)
возвращает true.
os
Программы теперь могут передавать пустое значение time.Time в функцию
Chtimes
чтобы оставить либо время доступа, либо время модификации неизменным.
В Windows метод
File.Chdir теперь изменяет текущий каталог на файл, вместо того чтобы всегда возвращать ошибку.
В Unix системах, если неблокирующий дескриптор передается в функцию
NewFile, вызов метода
File.Fd
теперь возвращает неблокирующий дескриптор. Ранее дескриптор преобразовывался в блокирующий режим.
В Windows вызов
Truncate для несуществующего файла раньше создавал пустой файл. Теперь возвращается ошибка, указывающая, что файл не существует.
В Windows вызов
TempDir теперь использует
GetTempPath2W если доступен, вместо GetTempPathW. Новое поведение является мерой усиления безопасности, которая предотвращает доступ к временным файлам, созданным процессами, работающими от имени SYSTEM, для процессов, не работающих от имени SYSTEM.
В Windows пакет os теперь поддерживает работу с файлами, имена которых, хранящиеся как UTF-16, не могут быть представлены как корректная UTF-8.
В Windows Lstat теперь разрешает символические ссылки для путей, заканчивающихся разделителем пути, согласно своему поведению на POSIX платформах.
Реализация интерфейса
io/fs.DirEntry,
возвращаемого функцией
ReadDir и методом
File.ReadDir,
теперь реализует метод String, который вызывает
io/fs.FormatDirEntry.
Реализация интерфейса
io/fs.FS, возвращаемого функцией
DirFS, теперь реализует интерфейсы
io/fs.ReadFileFS и
io/fs.ReadDirFS.
path/filepath
Реализация интерфейса
io/fs.DirEntry,
передаваемого в аргумент функции
WalkDir,
теперь реализует метод String, который вызывает
io/fs.FormatDirEntry.
reflect
В Go 1.21 метод ValueOf
больше не вынуждает свой аргумент быть размещённым в куче, позволяя
содержимому Value размещаться на стеке. Большинство
операций над Value также позволяют размещать базовое значение
на стеке.
Новый метод Value
Value.Clear
очищает содержимое карты или обнуляет содержимое среза.
Это соответствует новому встроенному элементу clear,
добавленному в язык.
Типы SliceHeader
и StringHeader
теперь устарели. В новом коде предпочтительно использовать
unsafe.Slice,
unsafe.SliceData,
unsafe.String,
или unsafe.StringData.
regexp
Regexp теперь определяет
методы MarshalText
и UnmarshalText.
Они реализуют
encoding.TextMarshaler
и
encoding.TextUnmarshaler
и будут использоваться пакетами, такими как
encoding/json.
runtime
Текстовые трассировки стека, создаваемые программами на Go, такие как
те, что создаются при аварийном завершении, вызове runtime.Stack
или сборке профиля горутин с помощью debug=2, теперь
включают идентификаторы горутин, создавших каждую горутину в трассировке стека.
При аварийном завершении приложений на Go теперь можно включить
Windows Error Reporting (WER), установив переменную окружения
GOTRACEBACK=wer или вызвав debug.SetTraceback("wer")
до аварийного завершения. За исключением включения WER, среда выполнения будет вести себя так же, как с GOTRACEBACK=crash.
На не-Windows системах GOTRACEBACK=wer игнорируется.
GODEBUG=cgocheck=2, тщательная проверка правил передачи указателей cgo,
больше не доступна как параметр отладки.
Вместо этого она доступна как эксперимент с использованием GOEXPERIMENT=cgocheck2.
В частности, это означает, что этот режим должен быть выбран во время сборки, а не во время запуска.
GODEBUG=cgocheck=1 по-прежнему доступен (и по-прежнему является значением по умолчанию).
В пакет runtime был добавлен новый тип Pinner.
Pinner может использоваться для "прикрепления" памяти Go,
чтобы она могла свободнее использоваться кодом, не являющимся Go. Например,
передача значений Go, ссылающихся на прикреплённую память Go, в C-код теперь разрешена.
Ранее любая такая вложенная ссылка запрещалась
правилами передачи указателей cgo.
См. документацию для получения дополнительных сведений.
runtime/metrics
Некоторые ранее внутренние метрики GC, такие как размер живой кучи, теперь доступны.
GOGC и GOMEMLIMIT также теперь доступны в качестве метрик.
runtime/trace
Сбор трассировок на amd64 и arm64 теперь требует значительно меньшего количества CPU: улучшение до 10x по сравнению с предыдущим релизом.
Трассировки теперь содержат явные события остановки мира (stop-the-world) для каждого из причин, по которым среда выполнения Go может остановить мир, а не только по причине сборки мусора.
sync
Новые функции OnceFunc,
OnceValue и
OnceValues
захватывают распространённое использование Once для ленивой инициализации значения при первом использовании.
syscall
В Windows функция
Fchdir теперь изменяет текущий каталог на свой аргумент, а не всегда возвращает ошибку.
В FreeBSD у типа
SysProcAttr
появилось новое поле Jail, которое может использоваться для помещения нового созданного процесса в изолированную среду (jailed environment).
В Windows пакет syscall теперь поддерживает работу с файлами, имена которых, хранящиеся как UTF-16, не могут быть представлены как корректная UTF-8.
Функции
UTF16ToString
и UTF16FromString
теперь конвертируют данные из UTF-16 в строки формата
WTF-8.
Это обратно совместимо, поскольку WTF-8 является надмножеством формата UTF-8, использовавшегося в предыдущих релизах.
Несколько значений ошибок теперь соответствуют новому
errors.ErrUnsupported,
так что errors.Is(err, errors.ErrUnsupported)
возвращает true.
ENOSYSENOTSUPEOPNOTSUPPEPLAN9(только для Plan 9)ERROR_CALL_NOT_IMPLEMENTED(только для Windows)ERROR_NOT_SUPPORTED(только для Windows)EWINDOWS(только для Windows)
testing
Новая опция -test.fullpath будет выводить полные пути
в сообщениях лога тестов, а не только базовые имена.
Новая функция Testing сообщает, является ли программа тестом, созданным командой go test.
testing/fstest
Вызов Open.Stat
возвращает тип, который теперь реализует метод String, вызывающий
io/fs.FormatFileInfo.
unicode
Пакет unicode и связанная с ним поддержка по всей системе были обновлены до
Unicode 15.0.0.
Порты
Darwin
Как сообщалось в заметках о релизе Go 1.20, Go 1.21 требует macOS 10.15 Catalina или более поздней версии; поддержка предыдущих версий была прекращена.
Windows
Как сообщалось в заметках о релизе Go 1.20, Go 1.21 требует как минимум Windows 10 или Windows Server 2016; поддержка предыдущих версий была прекращена.
ARM
При сборке дистрибутива Go с GOARCH=arm вне системы ARM (то есть при создании кросспилятора для ARM), значение переменной окружения GOARM теперь всегда устанавливается по умолчанию в 7.
Ранее значение по умолчанию зависело от характеристик системы сборки.
Если кросспилятор не создается, значение по умолчанию определяется путем анализа системы сборки. Это было верно и ранее, и остается таковым в Go 1.21. Изменилось поведение при создании кросспилятора.
WebAssembly
Новая директива go:wasmimport теперь может использоваться в программах на Go
для импорта функций из хоста WebAssembly.
Планировщик Go теперь намного более эффективно взаимодействует с циклом событий JavaScript, особенно в приложениях, которые часто блокируются на асинхронных событиях.
WebAssembly System Interface
Go 1.21 добавляет экспериментальный порт для
WebAssembly System Interface (WASI), Preview 1
(GOOS=wasip1, GOARCH=wasm).
В результате добавления нового значения GOOS
“wasip1”, файлы Go с именами *_wasip1.go
теперь игнорируются инструментами Go, кроме случаев, когда используется значение GOOS.
Если у вас уже существуют файлы, соответствующие этому шаблону, их нужно будет переименовать.
ppc64/ppc64le
В Linux, GOPPC64=power10 теперь генерирует инструкции с относительными адресами, префиксные инструкции и другие новые инструкции Power10. В AIX, GOPPC64=power10
генерирует инструкции Power10, но не генерирует инструкции с относительными адресами.
При сборке двоичных файлов без привязки к позиции для GOPPC64=power10
GOOS=linux GOARCH=ppc64le, пользователи могут ожидать уменьшения размера двоичных файлов в большинстве случаев, в некоторых случаях — на 3.5%. Двоичные файлы без привязки к позиции создаются для ppc64le с следующими значениями -buildmode:
c-archive, c-shared, shared, pie, plugin.
loong64
Порт linux/loong64 теперь поддерживает -buildmode=c-archive,
-buildmode=c-shared и -buildmode=pie.