Релиз 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 1.21 добавляет в язык три новых встроенных модуля.
- Новые функции min и max вычисляют наименьшее (или наибольшее для max) значение фиксированного числа заданных аргументов.
- Новая функция clear удаляет все элементы с карты или обнуляет все элементы среза.
Порядок инициализации пакетов теперь указан более точно. Новый алгоритм таков:
- Отсортируйте все пакеты по пути импорта.
- Повторяйте, пока список пакетов не станет пустым:
- Найдите в списке первый пакет, для которого все импорты уже инициализированы.
- Инициализируйте этот пакет и удалите его из списка.
Это может изменить поведение некоторых программ, которые полагаются на определенный порядок инициализации, не выраженный явным импортом. Поведение таких программ не было четко определено спецификацией в прошлых релизах. Новое правило дает однозначное определение.
Внесено множество улучшений, повышающих мощность и точность вывода типов.
- Функция (возможно, частично созданная универсальная) теперь может быть вызвана с аргументами, которые сами являются (возможно, частично созданными) универсальными функциями. Компилятор попытается вывести отсутствующие аргументы типа вызываемого объекта (как и раньше) и для каждого аргумента, который является универсальной функцией, экземпляр которой не полностью создан, его отсутствующие аргументы типа (новые). Типичными вариантами использования являются вызовы универсальных функций, работающих с контейнерами (например, slices.IndexFunc), где аргумент функции также может быть универсальным, а аргумент типа вызываемой функции и ее аргументы выводятся из типа контейнера. В более общем смысле универсальную функцию теперь можно использовать без явного создания экземпляра, когда она присваивается переменной или возвращается как значение результата, если аргументы типа можно вывести из присваивания.
- Вывод типа теперь также учитывает методы, когда значение присваивается интерфейсу: аргументы типа для параметров типа, используемых в сигнатурах методов, могут быть выведены из соответствующих типов параметров соответствующих методов.
- Точно так же, поскольку аргумент типа должен реализовывать все методы соответствующего ограничения, методы аргумента типа и ограничения совпадают, что может привести к выводу дополнительных аргументов типа.
- Если несколько нетипизированных постоянных аргументов разных типов (таких как нетипизированное целое число и нетипизированная константа с плавающей запятой) передаются параметрам с одним и тем же (не указанным иным образом) типом параметра типа вместо ошибки, теперь вывод типа определяет тип, используя тот же подход, что и у оператора с нетипизированными постоянными операндами. Это изменение приводит типы, выведенные из нетипизированных константных аргументов, в соответствие с типами константных выражений.
- Вывод типа теперь является точным при сопоставлении соответствующих типов в присваиваниях: типы компонентов (такие как элементы срезов или типы параметров в сигнатурах функций) должны быть идентичными (с учетом подходящих аргументов типа) для сопоставления, иначе вывод завершится ошибкой. Это изменение создает более точные сообщения об ошибках: если в прошлом вывод типа мог завершиться неправильно и привести к недопустимому присвоению, теперь компилятор сообщает об ошибке вывода, если два типа не могут совпасть.
В более общем плане описание вывода типов в спецификации языка было уточнено. Вместе все эти изменения делают вывод типов более мощным, а ошибки вывода менее неожиданными.
Go 1.21 включает в себя предварительную версию изменения языка, которое рассматривается для будущей версии Go: создание переменных цикла for для каждой итерации, а не для каждого цикла, чтобы избежать случайного совместного использования ошибок.
Go 1.21 теперь определяет, что если горутина находится в состоянии паники, а функция recovery была вызвана непосредственно отложенной функцией, возвращаемое значение recovery гарантированно не равно нулю. Чтобы гарантировать это, вызов panic со значением интерфейса nil (или нетипизированным nil) вызывает панику во время выполнения типа *runtime.PanicNilError.
Для поддержки программ, написанных для более старых версий Go, nil panic можно повторно включить, установив GODEBUG=panicnil=1. Этот параметр включается автоматически при компиляции программы, основной пакет которой находится в модуле, объявляющем go 1.20 или более ранней версии.
Инструменты
Go 1.21 добавляет улучшенную поддержку обратной и прямой совместимости в цепочке инструментов Go.
Чтобы улучшить обратную совместимость, Go 1.21 формализует использование Go переменной среды GODEBUG для управления поведением по умолчанию для изменений, которые не являются критическими в соответствии с политикой совместимости, но, тем не менее, могут привести к нарушению работы существующих программ. (Например, программы, зависящие от ошибочного поведения, могут сломаться, когда ошибка будет исправлена, но исправления ошибок не считаются критическими изменениями.) Когда Go должен внести такое изменение поведения, теперь он выбирает между старым и новым поведением на основе go в файле go.work рабочей области или в файле go.mod основного модуля. При обновлении до новой цепочки инструментов Go, но с сохранением исходной (старой) версии Go для строки go сохраняется поведение старой цепочки инструментов. Благодаря такой поддержке совместимости последняя цепочка инструментов Go всегда должна быть лучшей и наиболее безопасной реализацией старой версии Go.
Для улучшения совместимости 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.mod или go.work объявляет минимальные требования к более новой версии Go, команда go автоматически найдет и запустит эту версию. Новая директива цепочки инструментов устанавливает рекомендуемый минимальный набор инструментов для использования, который может быть новее, чем строгий минимум.
Команда go
Флаг сборки -pgo теперь по умолчанию имеет значение -pgo=auto, а ограничение на указание одного основного пакета в командной строке теперь снято. Если файл с именем default.pgo присутствует в каталоге основного пакета, команда go будет использовать его, чтобы включить оптимизацию на основе профиля для сборки соответствующей программы.
Флаг -C dir теперь должен быть первым флагом в командной строке при использовании.
Новая опция go test -fullpath печатает полные пути в сообщениях журнала тестирования, а не только базовые имена.
Флаг go test -c теперь поддерживает запись тестовых двоичных файлов для нескольких пакетов, каждый в pkg.test, где pkg — это имя пакета. Будет ошибкой, если более одного компилируемого тестового пакета имеют заданное имя пакета.
Флаг go test -o теперь принимает аргумент каталога, и в этом случае тестовые двоичные файлы записываются в этот каталог, а не в текущий каталог.
Cgo
В файлах, которые импортируют "C", набор инструментов Go теперь правильно сообщает об ошибках при попытках объявить методы Go для типов C.
Среда времени исполнения (Runtime)
При печати очень глубоких стеков runtime теперь печатает первые 50 (самые внутренние) фреймы, а затем нижние 50 (самые внешние) фреймы, а не просто печатает первые 100 фреймов. Это облегчает понимание того, как запускаются глубоко рекурсивные стеки, и особенно полезно для отладки переполнения стека.
На платформах Linux, которые поддерживают прозрачные огромные страницы (transparent huge pages), среда выполнения Go теперь более явно определяет, какие части кучи могут быть поддержаны огромными страницами. Это приводит к лучшему использованию памяти: для небольших куч должно использоваться меньше памяти (до 50 % в патологических случаях), тогда как для больших куч должно использоваться меньше испорченных огромных страниц для плотных частей кучи, что улучшает использование ЦП и задержку до 1%.
В результате внутренней настройки сборки мусора во время выполнения приложения могут сократить задержку хвоста приложения на 40% и небольшое снижение использования памяти. В некоторых приложениях также может наблюдаться небольшая потеря пропускной способности. Уменьшение использования памяти должно быть пропорционально потере пропускной способности, чтобы компромисс между пропускной способностью и памятью предыдущей версии можно было восстановить (с небольшим изменением задержки) путем небольшого увеличения GOGC и/или GOMEMLIMIT.
Вызовы из C в Go в потоках, созданных в C, требуют некоторой настройки для подготовки к выполнению Go. На платформах Unix эта настройка теперь сохраняется при нескольких вызовах из одного потока. Это значительно снижает накладные расходы на последующие вызовы C в Go с ~1–3 микросекунд на вызов до ~100–200 наносекунд на вызов.
Компилятор
Оптимизация на основе профиля (PGO, Profile-guide optimization), добавленная в качестве предварительной версии в Go 1.20, теперь готова для общего использования. PGO обеспечивает дополнительную оптимизацию кода, который определяется как "горячий" в соответствии с профилями производственных рабочих нагрузок. Как упоминалось в разделе команд Go, PGO включен по умолчанию для двоичных файлов, которые содержат профиль default.pgo в основном каталоге пакета. Улучшение производительности варьируется в зависимости от поведения приложения: в большинстве программ из репрезентативного набора программ Go наблюдается улучшение от 2 до 7% от включения PGO.
Сборки PGO теперь могут девиртуализировать вызовы некоторых методов интерфейса, добавляя конкретный вызов к наиболее распространенному вызываемому объекту. Это обеспечивает дальнейшую оптимизацию, например, встраивание вызываемого объекта.
Go 1.21 повышает скорость сборки до 6%, во многом благодаря сборке самого компилятора с помощью PGO.
Ассемблер
В amd64 безрамочные функции сборки nosplit больше не помечаются автоматически как NOFRAME. Вместо этого при желании атрибут NOFRAME должен быть явно указан, что уже происходит в других архитектурах, поддерживающих указатели фреймов. Благодаря этому среда выполнения теперь поддерживает указатели фреймов для переходов стека.
Улучшен верификатор, проверяющий неправильное использование R15 при динамической компоновке на amd64.
Компоновщик (Linker)
В 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 для добавления непосредственно в буфер.
context
Новая функция WithoutCancel возвращает копию контекста, которая не отменяется при отмене исходного контекста.
Новые функции WithDeadlineCause и WithTimeoutCause позволяют установить причину отмены контекста по истечении крайнего срока или таймера. Причину можно выяснить с помощью функции Cause.
Новая функция AfterFunc регистрирует функцию, которая будет запускаться после отмены контекста.
Оптимизация означает, что результаты вызова Background и TODO и преобразования их в общий тип можно считать равными. В предыдущих релизах они всегда были разными. Сравнение значений контекста на предмет равенства никогда не было четко определено, поэтому это не считается несовместимым изменением.
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 отменено и теперь установлено для возобновленных соединений, поддерживающих расширенный главный секрет.
Новый тип QUICConn обеспечивает поддержку реализаций QUIC, включая поддержку 0-RTT. Обратите внимание, что это само по себе не является реализацией QUIC, и 0-RTT по-прежнему не поддерживается в TLS.
Новая функция VersionName возвращает имя для номера версии TLS.
Были улучшены коды предупреждений TLS, отправляемые с сервера при ошибках аутентификации клиента. Раньше эти сбои всегда приводили к предупреждению о "плохом сертификате". Теперь при определенных сбоях будут использоваться более подходящие коды предупреждений, как определено в RFC 5246 и RFC 8446:
- Для подключений TLS 1.3, если сервер настроен на требование проверки подлинности клиента с помощью RequireAnyClientCert или RequireAndVerifyClientCert, а клиент не предоставляет сертификат, сервер теперь вернет предупреждение "требуется сертификат".
- Если клиент предоставляет сертификат, который не подписан набором доверенных центров сертификации, настроенных на сервере, сервер вернет предупреждение "неизвестный центр сертификации".
- Если клиент предоставляет сертификат, срок действия которого истек или еще не действителен, сервер вернет предупреждение "сертификат с истекшим сроком действия".
- Во всех других сценариях, связанных с ошибками аутентификации клиента, сервер по-прежнему возвращает "неверный сертификат".
crypto/x509
RevokedList.RevokedCertificates устарел и заменен новым полем RevokedCertificateEntries, которое является частью RevokedListEntry. RelocationListEntry содержит все поля в pkix.RevokedCertificate, а также код причины отзыва.
Ограничения имен теперь правильно применяются к нелистовым сертификатам, а не к сертификатам, в которых они выражены.
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.
errors
Новая ошибка ErrUnsupported предоставляет стандартизированный способ указать, что запрошенная операция не может быть выполнена, поскольку она не поддерживается. Например, вызов os.Link при использовании файловой системы, не поддерживающей жесткие ссылки.
flag
Новая функция BoolFunc и метод FlagSet.BoolFunc определяют флаг, который не требует аргумента, и вызывает функцию при использовании флага. Это похоже на Func, но с логическим флагом.
Определение флага (через Bool, BoolVar, Int, IntVar и т. д.) вызовет панику, если Set уже был вызван для флага с таким же именем. Это изменение предназначено для обнаружения случаев, когда изменения в порядке инициализации приводят к тому, что операции с флагами выполняются в другом порядке, чем ожидалось. Во многих случаях решение этой проблемы состоит в том, чтобы ввести явную зависимость пакета, чтобы правильно упорядочить определение перед любыми операциями Set.
go/ast
Новый предикат IsGenerated сообщает, содержит ли синтаксическое дерево файла специальный комментарий, который обычно указывает на то, что файл был создан с помощью инструмента.
Новое поле File.GoVersion записывает минимальную версию Go, необходимую для любых директив //go:build или // +build.
go/build
Пакет теперь анализирует директивы сборки (комментарии, начинающиеся с //go:) в заголовках файлов (перед объявлением пакета). Эти директивы доступны в новых полях пакета: Directives, TestDirectives и XTestDirectives.
go/build/constraint
Новая функция GoVersion возвращает минимальную версию Go, подразумеваемую выражением сборки.
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 возвращается клиентом и транспортом, когда сервер отвечает на запрос HTTPS ответом HTTP.
Пакет net/http теперь поддерживает error.ErrUnsupported, поскольку выражение error.Is(http.ErrNotSupported, error.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 (WER, Windows Error Reporting), установив переменную среды GOTRACEBACK=wer или вызвав debug.SetTraceback("wer") перед сбоем. За исключением включения WER, среда выполнения будет вести себя так же, как и при GOTRACEBACK=crash. В системах, отличных от Windows, GOTRACEBACK=wer игнорируется.
GODEBUG=cgocheck=2, тщательная проверка правил передачи указателей cgo, больше не доступен в качестве опции отладки. Вместо этого он доступен в качестве эксперимента с использованием GOEXPERIMENT=cgocheck2. В частности, это означает, что этот режим необходимо выбирать во время сборки, а не во время запуска.
GODEBUG=cgocheck=1 по-прежнему доступен (и по-прежнему используется по умолчанию).
В пакет среды выполнения добавлен новый тип Pinner. Пиннеры могут использоваться для "закрепления" памяти Go, чтобы ее можно было более свободно использовать кодом, отличным от Go. Например, теперь разрешена передача значений Go, которые ссылаются на закрепленную память Go, в код C. Ранее передача любой такой вложенной ссылки была запрещена правилами передачи указателей cgo.
runtime/metrics
Теперь доступны некоторые ранее внутренние показатели сборщика мусора, такие как размер динамической кучи. GOGC и GOMEMLIMIT теперь также доступны в качестве метрик.
runtime/trace
Сбор трассировок на amd64 и arm64 теперь требует существенно меньших затрат ЦП: до 10 раз больше, чем в предыдущей версии.
Трассировки теперь содержат явные события stop-the-world по любой причине, по которой среда выполнения Go может запустить stop-the-world, а не только для сборки мусора.
sync
Новые функции OnceFunc, OnceValue и OnceValues отражают распространенное использование Once для ленивой инициализации значения при первом использовании.
syscall
В Windows функция Fchdir теперь меняет текущий каталог на свой аргумент, а не всегда возвращает ошибку.
Во FreeBSD SysProcAttr имеет новое поле Jail, которое можно использовать для помещения вновь созданного процесса в изолированную среду.
В Windows пакет syscall теперь поддерживает работу с файлами, имена которых, сохраненные в формате UTF-16, не могут быть представлены как допустимые UTF-8. Функции UTF16ToString и UTF16FromString теперь преобразуют данные UTF-16 в строки WTF-8. Это обратно совместимо, поскольку WTF-8 является расширенным набором формата UTF-8, который использовался в более ранних релизах.
Несколько значений ошибок соответствуют новым error.ErrUnsupported, например, error.Is(err, error.ErrUnsupported) возвращает true.
- ENOSYS
- ENOTSUP
- EOPNOTSUPP
- EPLAN9 (только Plan 9)
- ERROR_CALL_NOT_IMPLEMENTED (только Windows)
- ERROR_NOT_SUPPORTED (только Windows)
- EWINDOWS (только Windows)
testing
Новая опция -test.fullpath будет печатать полные пути в сообщениях журнала тестирования, а не только базовые имена.
Новая функция тестирования сообщает, является ли программа тестом, созданным 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; поддержка предыдущих версий прекращена.
WebAssembly
Новую директиву go:wasmimport теперь можно использовать в программах Go для импорта функций с хоста WebAssembly.
Планировщик Go теперь гораздо эффективнее взаимодействует с циклом событий JavaScript, особенно в приложениях, которые часто блокируются при асинхронных событиях.
Системный интерфейс WebAssembly
В Go 1.21 добавлен экспериментальный порт в системный интерфейс WebAssembly (WASI), предварительная версия 1 (GOOS=wasip1, GOARCH=wasm).
В результате добавления нового значения GOOS "wasip1" файлы Go с именем *_wasip1.go теперь будут игнорироваться инструментами Go, за исключением случаев, когда используется это значение GOOS. Если у вас есть имена файлов, соответствующие этому шаблону, вам нужно будет переименовать их.
ppc64/ppc64le
В Linux GOPPC64=power10 теперь генерирует инструкции для PC, инструкции с префиксами и другие новые инструкции Power10. В AIX GOPPC64=power10 генерирует инструкции Power10, но не создает инструкции, относящиеся к PC.
При построении позиционно-независимых двоичных файлов для 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.
Читайте также:
Канал в Телеграм