вторник, 4 марта 2025 г.

Релиз Go 1.24

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

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

Go 1.24 теперь полностью поддерживает псевдонимы универсальных типов: псевдоним типа может быть параметризован как определенный тип. На данный момент эту функцию можно отключить, установив GOEXPERIMENT=noaliastypeparams; но настройка aliastypeparams будет удалена для Go 1.25.

Инструменты

Команда go

Модули Go теперь могут отслеживать зависимости исполняемых файлов с помощью директив инструментов в go.mod. Это устраняет необходимость в предыдущем обходном пути добавления инструментов в виде пустых импортов в файл, который обычно называется «tools.go». Команда go tool теперь может запускать эти инструменты в дополнение к инструментам, поставляемым с дистрибутивом Go.

Новый флаг -tool для go get приводит к добавлению директивы tool в текущий модуль для именованных пакетов в дополнение к добавлению директив require.

Новый меташаблон tool относится ко всем инструментам в текущем модуле. Это можно использовать для их обновления с помощью go get tool или для установки в каталог GOBIN с помощью go install tool.

Исполняемые файлы, созданные go run, и новое поведение go tool теперь кэшируются в кэше сборки Go. Это ускоряет повторные выполнения за счет увеличения кэша.

Команды go build и go install теперь принимают флаг -json, который сообщает о выходных данных сборки и сбоях в виде структурированного вывода JSON на стандартном выводе.

Кроме того, go test -json теперь сообщает о выходных данных сборки и сбоях в формате JSON, чередующемся с результатом теста JSON. Они различаются новыми типами действий, но если они вызывают проблемы в системе интеграции тестов, вы можете вернуться к текстовому выводу сборки с помощью настройки GODEBUG gotestjsonbuildtext=1.

Новая переменная среды GOAUTH обеспечивает гибкий способ аутентификации выборок частных модулей.

Команда go build теперь устанавливает версию основного модуля в скомпилированном двоичном файле на основе тега системы контроля версий и/или фиксации. Суффикс +dirty будет добавлен, если есть незафиксированные изменения. Используйте флаг -buildvcs=false, чтобы исключить информацию о контроле версий из двоичного файла.

Новая настройка GODEBUG toolchaintrace=1 может использоваться для отслеживания процесса выбора цепочки инструментов команды go.

Cgo

Cgo поддерживает новые аннотации для функций C для улучшения производительности во время выполнения. #cgo noescape cFunctionName сообщает компилятору, что память, переданная функции C cFunctionname, не экранируется. #cgo nocallback cFunctionName сообщает компилятору, что функция C cFunctionName не вызывает никаких функций Go.

В настоящее время Cgo отказывается компилировать вызовы функции C, которая имеет несколько несовместимых объявлений. Например, если f объявлена как void f(int) и void f(double), cgo сообщит об ошибке вместо того, чтобы, возможно, сгенерировать некорректную последовательность вызовов для f(0). Новое в этом релизе — лучший детектор для этого состояния ошибки, когда несовместимые объявления появляются в разных файлах.

Objdump

Инструмент objdump теперь поддерживает дизассемблирование на 64-битных LoongArch (GOARCH=loong64), RISC-V (GOARCH=riscv64) и S390X (GOARCH=s390x).

Vet

Новый анализатор тестов сообщает о распространенных ошибках в объявлениях тестов, фаззеров, бенчмарков и примеров в тестовых пакетах, таких как неправильно сформированные имена, неверные подписи или примеры, которые документируют несуществующие идентификаторы. Некоторые из этих ошибок могут привести к тому, что тесты не будут запускаться. Этот анализатор входит в подмножество анализаторов, которые запускаются go test.

Существующий анализатор printf теперь сообщает о диагностике для вызовов формы fmt.Printf(s), где s — это строка непостоянного формата без других аргументов. Такие вызовы почти всегда являются ошибкой, так как значение s может содержать символ %; вместо этого используйте fmt.Print. Эта проверка, как правило, выдает результаты в существующем коде, поэтому применяется только тогда, когда версия языка (указанная директивой go.mod go или комментариями //go:build) не ниже Go 1.24, чтобы избежать сбоев непрерывной интеграции при обновлении до набора инструментов Go 1.24.

Существующий анализатор buildtag теперь выдает диагностику, когда в директиве //go:build есть недопустимое ограничение сборки основной версии Go. Например, //go:build go1.23.1 ссылается на точечный релиз; вместо этого используйте //go:build go1.23.

Существующий анализатор copylock теперь выдает диагностику, когда переменная, объявленная в цикле «for» из 3 предложений, например for i := iter(); done(i); i = next(i) { ... }, содержит sync.Locker, например sync.Mutex. Go 1.22 изменил поведение этих циклов, чтобы создавать новую переменную для каждой итерации, копируя значение из предыдущей итерации; эта операция копирования небезопасна для блокировок.

GOCACHEPROG

Внутренний двоичный и тестовый механизм кэширования cmd/go теперь может быть реализован дочерними процессами, реализующими протокол JSON между инструментом cmd/go и дочерним процессом, названным переменной среды GOCACHEPROG. Ранее это было за GOEXPERIMENT.

Runtime

Несколько улучшений производительности runtime снизили нагрузку на процессор в среднем на 2–3% по набору репрезентативных тестов. Результаты могут различаться в зависимости от приложения. Эти улучшения включают новую встроенную реализацию карты на основе Swiss Tables, более эффективное распределение памяти для небольших объектов и новую реализацию внутреннего мьютекса во время выполнения.

Новую встроенную реализацию карты и новый внутренний мьютекс во время выполнения можно отключить, установив GOEXPERIMENT=noswissmap и GOEXPERIMENT=nospinbitmutex во время сборки соответственно.

Компилятор

Компилятор уже запрещал определять новые методы с типами приемников, которые были сгенерированы cgo, но это ограничение можно было обойти с помощью типа псевдонима. Go 1.24 теперь всегда сообщает об ошибке, если приемник обозначает тип, сгенерированный cgo, как напрямую, так и косвенно (через тип псевдонима).

Компоновщик

Компоновщик теперь по умолчанию генерирует идентификатор сборки GNU (заметка ELF NT_GNU_BUILD_ID) на платформах ELF и UUID (команда загрузки Mach-O LC_UUID) на macOS. Идентификатор сборки или UUID выводится из идентификатора сборки Go. Его можно отключить с помощью флага компоновщика -B none или переопределить с помощью флага компоновщика -B 0xNNNN с указанным пользователем шестнадцатеричным значением.

Bootstrap

Как упоминалось в примечаниях к релизу Go 1.22, Go 1.24 теперь требует Go 1.22.6 или более поздней версии для bootstrap. Ожидается, что Go 1.26 потребует точечный релиз Go 1.24 или более поздней версии для bootstrap.

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

Ограниченный каталогом доступ к файловой системе

Новый тип os.Root обеспечивает возможность выполнять операции с файловой системой в определенном каталоге.

Функция os.OpenRoot открывает каталог и возвращает os.Root. Методы os.Root работают в каталоге и не допускают пути, ссылающиеся на местоположения за пределами каталога, включая те, которые следуют по символическим ссылкам из каталога. Методы os.Root отражают большинство операций с файловой системой, доступных в пакете os, включая, например, os.Root.Open, os.Root.Create, os.Root.Mkdir и os.Root.Stat.

Новая функция бенчмарка

Теперь бенчмарки могут использовать более быстрый и менее подверженный ошибкам метод testing.B.Loop для выполнения итераций бенчмарка, например for b.Loop() { ... } вместо типичных структур цикла, включающих b.N, например for range b.N. Это дает два существенных преимущества:

  • Функция бенчмарка будет выполняться ровно один раз за -count, поэтому дорогостоящие шаги настройки и очистки выполняются только один раз.
  • Параметры вызова функции и результаты сохраняются, что не позволяет компилятору полностью оптимизировать тело цикла.

Улучшенные финализаторы

Новая функция runtime.AddCleanup — это механизм финализации, который более гибкий, более эффективный и менее подвержен ошибкам, чем runtime.SetFinalizer. AddCleanup присоединяет функцию очистки к объекту, которая будет запущена, когда объект больше не будет доступен. Однако, в отличие от SetFinalizer, несколько очисток могут быть присоединены к одному объекту, очистки могут быть присоединены к внутренним указателям, очистки обычно не вызывают утечек, когда объекты образуют цикл, и очистки не задерживают освобождение объекта или объектов, на которые он указывает. Новый код должен предпочесть AddCleanup, а не SetFinalizer.

Новый пакет weak

Новый пакет weak предоставляет слабые указатели.

Слабые указатели — это примитив низкого уровня, предоставляемый для создания структур с эффективным использованием памяти, таких как слабые карты для связывания значений, карты канонизации для всего, что не охвачено package unique, и различные виды кэшей. Для поддержки этих вариантов использования этот релиз также предоставляет runtime.AddCleanup и maphash.Comparable.

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

Новый пакет crypto/mlkem реализует ML-KEM-768 и ML-KEM-1024.

ML-KEM — это постквантовый механизм обмена ключами, ранее известный как Kyber и описанный в FIPS 203.

Новые пакеты crypto/hkdf, crypto/pbkdf2 и crypto/sha3

Новый пакет crypto/hkdf реализует функцию вывода ключа Extract-and-Expand на основе HMAC HKDF, как определено в RFC 5869.

Новый пакет crypto/pbkdf2 реализует функцию вывода ключа на основе пароля PBKDF2, как определено в RFC 8018.

Новый пакет crypto/sha3 реализует хэш-функцию SHA-3 и функции расширяемого вывода SHAKE и cSHAKE, как определено в FIPS 202.

Все три пакета основаны на уже существующих пакетах golang.org/x/crypto/....

Соответствие FIPS 140-3

Этот релиз включает новый набор механизмов для обеспечения соответствия FIPS 140-3.

Go Cryptographic Module — это набор внутренних стандартных пакетов библиотеки, которые прозрачно используются для реализации алгоритмов, одобренных FIPS 140-3. Приложения не требуют никаких изменений для использования Go Cryptographic Module для одобренных алгоритмов.

Новая переменная среды GOFIPS140 может использоваться для выбора версии Go Cryptographic Module для использования в сборке. Новая настройка fips140 GODEBUG может использоваться для включения режима FIPS 140-3 во время выполнения.

Go 1.24 включает Go Cryptographic Module версии v1.0.0, которая в настоящее время проходит тестирование в лаборатории, аккредитованной CMVP.

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

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

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

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

Пакет synctest является экспериментальным и должен быть включен путем установки GOEXPERIMENT=synctest во время сборки. API пакета может быть изменен в будущих релизах.

Минорные изменения в библиотеке

archive

Реализации (*Writer).AddFS в archive/zip и archive/tar теперь записывают заголовок каталога для пустого каталога.

bytes

Пакет bytes добавляет несколько функций, которые работают с итераторами:

  • Lines возвращает итератор по строкам, завершающимся символом новой строки, в байтовом срезе.
  • SplitSeq возвращает итератор по всем подсрезам байтового среза, разделенного вокруг разделителя.
  • SplitAfterSeq возвращает итератор по подсрезам байтового среза, разделенного после каждого экземпляра разделителя.
  • FieldsSeq возвращает итератор по подсрезам байтового среза, разделенного вокруг пробельных символов, как определено unicode.IsSpace.
  • FieldsFuncSeq возвращает итератор по подсрезам байтового среза, разделенного вокруг кодовых точек Unicode, удовлетворяющих предикату.

crypto/aes

Значение, возвращаемое NewCipher, больше не реализует методы NewCTR, NewGCM, NewCBCEncrypter и NewCBCDecrypter. Эти методы не были документированы и доступны не на всех архитектурах. Вместо этого значение Block должно передаваться непосредственно соответствующим функциям crypto/cipher. На данный момент crypto/cipher по-прежнему проверяет эти методы в значениях Block, даже если они больше не используются стандартной библиотекой.

crypto/cipher

Новая функция NewGCMWithRandomNonce возвращает AEAD, который реализует AES-GCM, генерируя случайный одноразовый код во время Seal и добавляя его к зашифрованному тексту.

Реализация Stream, возвращаемая NewCTR при использовании с crypto/aes, теперь в несколько раз быстрее на amd64 и arm64.

NewOFB, NewCFBEncrypter и NewCFBDecrypter теперь устарели. Режимы OFB и CFB не аутентифицированы, что обычно позволяет активным атакам манипулировать и восстанавливать открытый текст. Рекомендуется, чтобы приложения использовали режимы AEAD. Если требуется неаутентифицированный режим Stream, используйте NewCTR.

crypto/ecdsa

PrivateKey.Sign теперь создает детерминированную подпись в соответствии с RFC 6979, если случайный источник равен нулю.

crypto/md5

Значение, возвращаемое md5.New, теперь также реализует интерфейс encoding.BinaryAppender.

crypto/rand

Функция Read теперь гарантированно не даст сбой. Она всегда будет возвращать nil в качестве результата ошибки. Если Read столкнется с ошибкой при чтении из Reader, программа безвозвратно завершится сбоем. Обратите внимание, что API платформы, используемые Reader по умолчанию, задокументированы как всегда успешные, поэтому это изменение должно повлиять только на программы, которые переопределяют переменную Reader. Исключением являются ядра Linux до версии 3.17, где Reader по умолчанию все еще открывает /dev/urandom и может дать сбой.

В Linux 6.11 и более поздних версиях Reader теперь использует системный вызов getrandom через vDSO. Это в несколько раз быстрее, особенно для небольших чтений.

В OpenBSD Reader теперь использует arc4random_buf(3).

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

crypto/rsa

GenerateKey теперь возвращает ошибку, если запрашивается ключ длиной менее 1024 бит. Все методы Sign, Verify, Encrypt и Decrypt теперь возвращают ошибку, если используются с ключом длиной менее 1024 бит. Такие ключи небезопасны и не должны использоваться. Настройка GODEBUG rsa1024min=0 восстанавливает старое поведение, но рекомендуется делать это только при необходимости и только в тестах, например, добавляя строку //go:debug rsa1024min=0 в тестовый файл. Новый пример GenerateKey предоставляет простой в использовании стандартный 2048-битный тестовый ключ.

Теперь безопасно и более эффективно вызывать PrivateKey.Precompute перед PrivateKey.Validate. Precompute теперь быстрее при наличии частично заполненных PrecomputedValues, например, при демаршалировании ключа из JSON.

Пакет теперь отклоняет больше недействительных ключей, даже если Validate не вызывается, а GenerateKey может возвращать новые ошибки для сломанных случайных источников. Поля Primes и Precomputed PrivateKey теперь используются и проверяются, даже если некоторые значения отсутствуют.

SignPKCS1v15 и VerifyPKCS1v15 теперь поддерживают SHA-512/224, SHA-512/256 и SHA-3.

GenerateKey теперь использует немного другой метод для генерации закрытой экспоненты (тотиент Кармайкла вместо тотиента Эйлера). Редкие приложения, которые внешне регенерируют ключи только из простых множителей, могут давать разные, но совместимые результаты.

Операции с открытыми и закрытыми ключами теперь выполняются в два раза быстрее на wasm.

crypto/sha1

Значение, возвращаемое sha1.New, теперь также реализует интерфейс encoding.BinaryAppender.

crypto/sha256

Значения, возвращаемые sha256.New и sha256.New224, теперь также реализуют интерфейс encoding.BinaryAppender.

crypto/sha512

Значения, возвращаемые sha512.New, sha512.New384, sha512.New512_224 и sha512.New512_256, теперь также реализуют интерфейс encoding.BinaryAppender.

crypto/subtle

Новая функция WithDataIndependentTiming позволяет пользователю запускать функцию с включенными функциями, специфичными для архитектуры, которые гарантируют, что определенные инструкции являются инвариантными по времени значениями данных. Это можно использовать для того, чтобы убедиться, что код, разработанный для выполнения в постоянном времени, не оптимизирован функциями уровня ЦП, так что он работает в переменном времени. В настоящее время WithDataIndependentTiming использует бит PSTATE.DIT на arm64 и является пустой операцией на всех других архитектурах. GODEBUG настройка dataindependenttiming=1 включает режим DIT для всей программы Go.

Выход XORBytes должен точно перекрываться или не перекрываться входами. Раньше поведение было неопределенным, а теперь XORBytes паникует.

crypto/tls

Сервер TLS теперь поддерживает Encrypted Client Hello (ECH). Эту функцию можно включить, заполнив поле Config.EncryptedClientHelloKeys.

Новый механизм обмена ключами X25519MLKEM768 после квантового режима теперь поддерживается и включается по умолчанию, когда Config.CurvePreferences равен нулю. Параметр GODEBUG tlsmlkem=0 отменяет значение по умолчанию. Это может быть полезно при работе с неисправными серверами TLS, которые некорректно обрабатывают большие записи, вызывая тайм-аут во время рукопожатия.

Поддержка экспериментального обмена ключами X25519Kyber768Draft00 была удалена.

Порядок обмена ключами теперь полностью обрабатывается пакетом crypto/tls. Порядок Config.CurvePreferences теперь игнорируется, а содержимое используется только для определения того, какие обмены ключами следует включить при заполнении поля.

Новое поле ClientHelloInfo.Extensions содержит идентификаторы расширений, полученных в сообщении Client Hello. Это может быть полезно для идентификации клиентов TLS.

crypto/x509

Настройка x509sha1 GODEBUG была удалена. Certificate.Verify больше не поддерживает подписи на основе SHA-1.

OID теперь реализует интерфейсы encoding.BinaryAppender и encoding.TextAppender.

Поле политик сертификатов по умолчанию изменилось с Certificate.PolicyIdentifiers на Certificate.Policies. При анализе сертификатов будут заполнены оба поля, но при создании сертификатов политики теперь будут взяты из поля Certificate.Policies вместо поля Certificate.PolicyIdentifiers. Это изменение можно отменить с помощью настройки GODEBUG x509usepolicies=0.

CreateCertificate теперь будет генерировать серийный номер с использованием метода, соответствующего RFC 5280, при передаче шаблона с нулевым полем Certificate.SerialNumber вместо сбоя.

Certificate.Verify теперь поддерживает проверку политики, как определено в RFC 5280 и RFC 9618. Новое поле VerifyOptions.CertificatePolicies может быть установлено на приемлемый набор OID политики. Из Certificate.Verify будут возвращены только цепочки сертификатов с допустимыми графами политики.

MarshalPKCS8PrivateKey теперь возвращает ошибку вместо маршалинга недействительного ключа RSA. (MarshalPKCS1PrivateKey не возвращает ошибку, и его поведение при предоставлении недействительных ключей по-прежнему не определено.)

ParsePKCS1PrivateKey и ParsePKCS8PrivateKey теперь используют и проверяют закодированные значения CRT, поэтому могут отклонять недействительные ключи RSA, которые были приняты ранее. Используйте настройку GODEBUG x509rsacrt=0, чтобы вернуться к пересчету значений CRT.

debug/elf

Пакет debug/elf добавляет поддержку обработки версий символов в динамических файлах ELF (исполняемый и связываемый формат). Новый метод File.DynamicVersions возвращает список динамических версий, определенных в файле ELF. Новый метод File.DynamicVersionNeeds возвращает список динамических версий, требуемых этим файлом ELF, которые определены в других объектах ELF. Наконец, новые поля Symbol.HasVersion и Symbol.VersionIndex указывают версию символа.

encoding

Два новых интерфейса, TextAppender и BinaryAppender, были введены для добавления текстового или двоичного представления объекта к байтовому срезу. Эти интерфейсы предоставляют ту же функциональность, что и TextMarshaler и BinaryMarshaler, но вместо того, чтобы каждый раз выделять новый срез, они добавляют данные непосредственно к существующему срезу. Эти интерфейсы теперь реализуются стандартными библиотечными типами, которые уже реализовали TextMarshaler и/или BinaryMarshaler.

encoding/json

При маршалинге поле структуры с новой опцией omitzero в теге поля структуры будет опущено, если его значение равно нулю. Если тип поля имеет метод IsZero() bool, он будет использоваться для определения, равно ли значение нулю. В противном случае значение равно нулю, если это нулевое значение для его типа. Тег поля omitzero более понятен и менее подвержен ошибкам, чем omitempty, когда намерение состоит в том, чтобы опустить нулевые значения. В частности, в отличие от omitempty, omitzero опускает нулевые значения time.Time, что является распространенным источником проблем.

Если указаны и omitempty, и omitzero, поле будет опущено, если значение либо пустое, либо нулевое (или оба).

UnmarshalTypeError.Field теперь включает встроенные структуры для предоставления более подробных сообщений об ошибках.

go/types

Все структуры данных go/types, которые предоставляют последовательности с помощью пары методов, таких как Len() int и At(int) T, теперь также имеют методы, которые возвращают итераторы, что позволяет упростить код, например:

params := fn.Type.(*types.Signature).Params()
for i := 0; i < params.Len(); i++ {
    use(params.At(i))
}

к виду:

for param := range fn.Signature().Params().Variables() {
    use(param)
}

Добавлены методы: Interface.EmbeddedTypes, Interface.ExplicitMethods, Interface.Methods, MethodSet.Methods, Named.Methods, Scope.Children, Struct.Fields, Tuple.Variables, TypeList.Types, TypeParamList.TypeParams, Union.Terms.

hash/adler32

Значение, возвращаемое New, теперь также реализует интерфейс encoding.BinaryAppender.

hash/crc32

Значения, возвращаемые New и NewIEEE, теперь также реализуют интерфейс encoding.BinaryAppender.

hash/crc64

Значение, возвращаемое New, теперь также реализует интерфейс encoding.BinaryAppender.

hash/fnv

Значения, возвращаемые New32, New32a, New64, New64a, New128 и New128a, теперь также реализуют интерфейс encoding.BinaryAppender.

hash/maphash

Новые функции Comparable и WriteComparable могут вычислять хеш любого сопоставимого значения. Они позволяют хешировать все, что может использоваться в качестве ключа карты Go.

log/slog

Новый DiscardHandler — это обработчик, который никогда не включается и всегда отбрасывает свой вывод.

Level и LevelVar теперь реализуют интерфейс encoding.TextAppender.

math/big

Float, Int и Rat теперь реализуют интерфейс encoding.TextAppender.

math/rand

Вызовы устаревшей функции Seed верхнего уровня больше не имеют никакого эффекта. Чтобы восстановить старое поведение, используйте настройку GODEBUG randseednop=0.

math/rand/v2

ChaCha8 и PCG теперь реализуют интерфейс encoding.BinaryAppender.

net

ListenConfig теперь использует MPTCP по умолчанию в системах, где он поддерживается (в настоящее время только в Linux).

IP теперь реализует интерфейс encoding.TextAppender.

net/http

Ограничение Transport на информационные ответы 1xx, полученные в ответ на запрос, изменилось. Ранее он прерывал запрос и возвращал ошибку после получения более 5 ответов 1xx. Теперь он возвращает ошибку, если общий размер всех ответов 1xx превышает настройку конфигурации Transport.MaxResponseHeaderBytes.

Кроме того, когда запрос имеет хук трассировки net/http/httptrace.ClientTrace.Got1xxResponse, теперь нет ограничений на общее количество ответов 1xx. Хук Got1xxResponse может вернуть ошибку, чтобы прервать запрос.

Transport и Server теперь имеют поле HTTP2, которое позволяет настраивать параметры протокола HTTP/2.

Новые поля Server.Protocols и Transport.Protocols предоставляют простой способ настройки протоколов HTTP, используемых сервером или клиентом.

Сервер и клиент могут быть настроены для поддержки незашифрованных соединений HTTP/2.

Когда Server.Protocols содержит UnencryptedHTTP2, сервер будет принимать соединения HTTP/2 на незашифрованных портах. Сервер может принимать как HTTP/1, так и незашифрованный HTTP/2 на одном и том же порту.

Если Transport.Protocols содержит UnencryptedHTTP2 и не содержит HTTP1, транспорт будет использовать незашифрованный HTTP/2 для http:// URL-адресов. Если транспорт настроен на использование как HTTP/1, так и незашифрованного HTTP/2, он будет использовать HTTP/1.

Поддержка незашифрованного HTTP/2 использует «HTTP/2 с предшествующими знаниями» (RFC 9113, раздел 3.3). Устаревший заголовок «Upgrade: h2c» не поддерживается.

net/netip

Addr, AddrPort и Prefix теперь реализуют интерфейсы encoding.BinaryAppender и encoding.TextAppender.

net/url

URL теперь также реализует интерфейс encoding.BinaryAppender.

os/user

В Windows Current теперь можно использовать в Windows Nano Server. Реализация была обновлена, чтобы избежать использования функций из библиотеки NetApi32, которая недоступна в Nano Server.

В Windows Current, Lookup и LookupId теперь поддерживают следующие встроенные учетные записи пользователей служб:

  • NT AUTHORITY\SYSTEM
  • NT AUTHORITY\LOCAL SERVICE
  • NT AUTHORITY\NETWORK SERVICE

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

В Windows Current теперь возвращает пользователя-владельца процесса, когда текущий поток выдает себя за другого пользователя. Ранее он возвращал ошибку.

regexp

Теперь Regexp реализует интерфейс encoding.TextAppender.

runtime

Функция GOROOT теперь устарела. В новом коде предпочтительнее использовать системный путь для поиска двоичного файла «go» и использовать go env GOROOT для поиска его GOROOT.

strings

Пакет strings добавляет несколько функций, которые работают с итераторами:

  • Lines возвращает итератор по строкам, завершающимся символом новой строки, в строке.
  • SplitSeq возвращает итератор по всем подстрокам строки, разделенной по разделителю.
  • SplitAfterSeq возвращает итератор по подстрокам строки, разделенной после каждого экземпляра разделителя.
  • FieldsSeq возвращает итератор по подстрокам строки, разделенной по пробельным символам, как определено в unicode.IsSpace.
  • FieldsFuncSeq возвращает итератор по подстрокам строки, разделенной вокруг последовательностей кодовых точек Unicode, удовлетворяющих предикату.

sync

Реализация sync.Map была изменена, что повысило производительность, особенно для изменений карт. Например, изменения непересекающихся наборов ключей с гораздо меньшей вероятностью будут конфликтовать на больших картах, и больше не требуется время наращивания для достижения низкоконкурентных загрузок из карты.

Если у вас возникнут какие-либо проблемы, установите GOEXPERIMENT=nosynchashtriemap во время сборки, чтобы вернуться к старой реализации, и сообщите о проблеме.

testing

Новые методы T.Context и B.Context возвращают контекст, который отменяется после завершения теста и до запуска функций очистки теста.

Новые методы T.Chdir и B.Chdir можно использовать для изменения рабочего каталога на время теста или бенчмарка.

text/template

Теперь шаблоны поддерживают range-over-func и range-over-int.

time

Теперь Time реализует интерфейсы encoding.BinaryAppender и encoding.TextAppender.

Порты

Linux

Как было объявлено в примечаниях к релизу Go 1.23, для Go 1.24 требуется ядро Linux версии 3.2 или более поздней.

Darwin

Go 1.24 — последний релиз, который будет работать на macOS 11 Big Sur. Для Go 1.25 потребуется macOS 12 Monterey или более поздней версии.

WebAssembly

Директива компилятора go:wasmexport добавлена для программ Go для экспорта функций на хост WebAssembly.

В WebAssembly System Interface Preview 1 (GOOS=wasip1 GOARCH=wasm) Go 1.24 поддерживает сборку программы Go в качестве реактора/библиотеки, указав флаг сборки -buildmode=c-shared.

Теперь больше типов разрешено в качестве типов аргументов или результатов для функций go:wasmimport. В частности, разрешены bool, string, uintptr и указатели на определенные типы, а также 32- и 64-битные целые и float типы и unsafe.Pointer, которые уже разрешены. Эти типы также разрешены в качестве типов аргументов или результатов для функций go:wasmexport.

Файлы поддержки для WebAssembly были перемещены в lib/wasm из misc/wasm.

Начальный размер памяти значительно уменьшен, особенно для небольших приложений WebAssembly.

Windows

32-битный порт windows/arm (GOOS=windows GOARCH=arm) отмечен как сломанный.


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


купить игрушку gopher

пятница, 18 октября 2024 г.

Как итерировать по символам в строках Go

В Go итерация по строке по ее символам (или знакам) может быть выполнена несколькими различными способами.

Использование цикла for...range

Наиболее распространенный и идиоматический способ итерации по строке в Go — использование цикла for...range. Этот метод правильно обрабатывает символы Unicode, рассматривая каждый символ как руну (что является псевдонимом для int32). Вот пример:

package main

import "fmt"

func main() {
    str := "Hello, 世界" // Строка с символами ASCII и не-ASCII

    for index, char := range str {
        fmt.Printf("Index: %d, Character: %c\n", index, char)
    }
}

Вывод:

Index: 0, Character: H
Index: 1, Character: e
Index: 2, Character: l
Index: 3, Character: l
Index: 4, Character: o
Index: 5, Character: ,
Index: 6, Character:
Index: 7, Character: 世
Index: 8, Character: 界

Использование стандартного цикла for с рунами

Если вы предпочитаете использовать традиционный цикл for, вы можете преобразовать строку в срез рун. Это позволяет вам перебирать каждый символ, сохраняя правильное представление символов Unicode:

package main

import "fmt"

func main() {
    str := "Hello, 世界"
    runes := []rune(str) // Преобразовать строку в срез рун

    for i := 0; i < len(runes); i++ {
        fmt.Printf("Rune %d is '%c'\n", i, runes[i])
    }
}

Вывод:

Rune 0 is 'H'
Rune 1 is 'e'
Rune 2 is 'l'
Rune 3 is 'l'
Rune 4 is 'o'
Rune 5 is ','
Rune 6 is ' '
Rune 7 is '世'
Rune 8 is '界'

Использование метода strings.Split

Другой подход — использовать метод strings.Split для разделения строки на отдельные символы. Однако этот метод может быть не таким эффективным или идиоматичным, как предыдущие методы:

package main

import (
    "fmt"
    "strings"
)

func main() {
    str := "Hello, 世界"
    chars := strings.Split(str, "") // Разделить строку на отдельные символы

    for _, char := range chars {
        fmt.Printf("Character: %s\n", char)
    }
}

Вывод:

Character: H
Character: e
Character: l
Character: l
Character: o
Character: ,
Character:
Character: 世
Character: 界

В Go предпочтительным способом перебора строк по символам является использование цикла for...range, поскольку он автоматически обрабатывает кодировку UTF-8 и обеспечивает простой способ доступа к каждому символу как к руне. В качестве альтернативы преобразование строки в срез рун обеспечивает больший контроль с помощью традиционной индексации. Метод strings.Split также можно использовать, но он менее эффективен для этой цели. Понимание этих методов поможет вам эффективно работать со строками в Go.


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


Строки как тип данных в Go

В Go (Golang) строка — это фундаментальный тип данных, используемый для представления последовательности символов. Он широко используется для обработки текста и необходим для различных задач программирования.

Характеристики строк в Go

Неизменяемость - после создания строки ее значение не может быть изменено. Любая операция, которая, как кажется, изменяет строку, на самом деле создает новую строку. Эта неизменяемость помогает оптимизировать использование памяти и обеспечить безопасность потоков.

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

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

Создание строк

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

Интерпретируемые литералы - поддерживают escape-последовательности (например, "\n" для новой строки).

str1 := "Hello, World!"

Необработанные литералы - заключены в обратные кавычки, они не поддерживают escape-последовательности и могут охватывать несколько строк.

str2 := `Это необработанный строковый литерал,
который может охватывать несколько строк.`

Операции и функции со строками

Go предоставляет несколько встроенных функций и методов для работы со строками, в основном через пакет strings. Некоторые распространенные операции включают:

Длина - используйте len() для получения количества байтов в строке.

length := len(str1) // Возвращает длину str1

Конкатенация - строки можно объединять с помощью оператора +.

combined := str1 + " " + str2

Подстрока - можно извлекать подстроки с помощью синтаксиса среза.

sub := str1[0:5] // "Hello"

Поиск и замена - функции, такие как strings.Contains(), strings.Replace() и strings.Index(), помогают находить подстроки или заменять части строк.

Пример кода

Вот простой пример, демонстрирующий создание строки и некоторые базовые операции:

package main

import (
    "fmt"
    "strings"
)

func main() {
    // Создание строк
    greeting := "Hello"
    name := "World"

    // Объединение строк
    message := greeting + ", " + name + "!"
    fmt.Println(message) // Вывод: Hello, World!

    // Проверка длины
    fmt.Println("Длина:", len(message)) // Вывод: Длина: 13

    // Поиск подстроки
    index := strings.Index(message, "World")
    fmt.Println("Индекс 'World':", index) // Вывод: Индекс 'World': 7

    // Замена подстроки
    newMessage := strings.Replace(message, "World", "Gopher", 1)
    fmt.Println(newMessage) // Вывод: Hello, Gopher!
}

Строки в Go — мощный, но простой в использовании инструмент, предоставляющий основные функции для обработки текста, обеспечивая при этом эффективность за счет неизменяемости и кодировки UTF-8. Понимание того, как эффективно работать со строками, имеет решающее значение для любого разработчика Go, поскольку они составляют основу большинства приложений, работающих с текстовыми данными.


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


пятница, 27 сентября 2024 г.

Где в памяти располагаются переменные в Golang

В Go переменной соответствует область памяти, которая может располагаться либо на стеке, либо в куче, в зависимости от типа данных этой переменной. Рассмотрим оба случая:

На стеке

Переменные размещаются на стеке (stack), когда они локальны для функции или метода. Например, если переменная объявлена внутри функции:

func main() {
    var myVar string // Переменная 'myVar' будет находиться на стеке
}

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

В куче (heap)

Переменная будет находиться в куче, если она является глобальной или создана с использованием ключевого слова new.

Глобальные переменные

package main

var myVar string // Переменная 'myVar' будет находиться в куче

func main() {}

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

Создание переменной через new

package main

import "fmt"

func main() {
    var myVar *string = new(string) // Переменная 'myVar' будет находиться в куче
    fmt.Println(*myVar)             // Результат будет nil
    
    *myVar = "Hello, World!"        // Заполнение значения по адресу переменной
    fmt.Println(*myVar)             // Вывод: Hello, World!
}

При использовании оператора new, создается новая область памяти в куче и возвращается ее адрес.

Таким образом, чтобы определить, где именно в памяти находится переменная, нужно проанализировать её использование в коде:

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

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


Как Golang работает с памятью

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

Автоматическое управление памятью

Компилятор Go автоматически выделяет и освобождает память для переменных и структур данных. Когда переменная выходит из области видимости, ее память автоматически освобождается за счет работы сборщика мусора. Это упрощает написание программ и уменьшает количество ошибок, связанных с утечками памяти.

Память, выделенная в стеке

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

Динамическая память (куча, heap)

Переменные, созданные с помощью оператора new, размещаются в куче. Куча используется для хранения объектов, которые должны существовать дольше одной функции. Управление памятью в куче осуществляется через сборщик мусора, который периодически сканирует память и освобождает объекты, на которые больше нет ссылок.

Сборка мусора

Сборщик мусора в Go является многопоточным и может работать параллельно с другими процессами программы. Он не блокирует выполнение других потоков и не прерывает работу приложения. Это позволяет Go эффективно управлять памятью даже в многопоточных приложениях.

Безопасность памяти

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

Высокая производительность

Так как Go использует механизмы операционной системы для управления памятью и сборки мусора, это позволяет добиться высокой производительности при работе с большими объемами данных.


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


среда, 28 августа 2024 г.

Релиз Go 1.23

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

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

Go 1.23 делает эксперимент (Go 1.22) "range-over-func" частью языка. "range" в цикле "for-range" теперь принимает функции итератора следующих типов

func(func() bool)
func(func(K) bool)
func(func(K, V) bool)

как выражения диапазона. Вызовы функции аргумента итератора создают значения итерации для цикла "for-range".

Go 1.23 включает предварительную поддержку псевдонимов универсальных типов. Создание цепочки инструментов с GOEXPERIMENT=aliastypeparams включает эту функцию в пакете. (Использование универсальных псевдонимов за пределами границ пакета пока не поддерживается.)

Инструменты

Телеметрия

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

Телеметрия Go — это включаемая по настройке система, управляемая командой go telemetry. По умолчанию программы цепочки инструментов собирают статистику в файлах счетчиков, которые можно проверять локально, но в остальном не используются (локальная телеметрия go).

Чтобы помочь разработчикам языка поддерживать хорошую работу Go и понимать использование Go рассмотрите возможность включения телеметрии Go, запустив go telemetry on. В этом режиме анонимные отчеты счетчиков еженедельно загружаются на telemetry.go.dev, где они объединяются в графики и также становятся доступными для загрузки любыми участниками Go или пользователями, желающими проанализировать данные.

Команда Go

Установка переменной среды GOROOT_FINAL больше не имеет эффекта. Дистрибутивы, которые устанавливают команду go в местоположение, отличное от $GOROOT/bin/go, должны устанавливать символическую ссылку вместо перемещения или копирования двоичного файла go.

Новый флаг go env -changed заставляет команду печатать только те настройки, эффективное значение которых отличается от значения по умолчанию, которое было бы получено в пустой среде без предварительного использования флага -w.

Новый флаг go mod tidy -diff заставляет команду не изменять файлы, а вместо этого печатать необходимые изменения в виде единого diff. Он завершается с ненулевым кодом, если требуются обновления.

Команда go list -m -json теперь включает новые поля Sum и GoModSum. Это похоже на существующее поведение команды go mod download -json.

Новая директива godebug в go.mod и go.work объявляет настройку GODEBUG для применения к используемому рабочему модулю или рабочему пространству.

Vet

Подкоманда go vet теперь включает анализатор stdversion, который помечает ссылки на символы, которые слишком новые для версии Go, действующей в ссылающемся файле. (Эффективная версия определяется директивой go в файле go.mod, включающем файл, и любыми ограничениями //go:build в файле.)

Например, она выдаст диагностику для ссылки на функцию reflect.TypeFor (введенную в go1.22) из ​​файла в модуле, файл go.mod которого указывает go 1.21.

Cgo

cmd/cgo поддерживает новый флаг -ldflags для передачи флагов компоновщику C. Команда go использует его автоматически, избегая ошибок “argument list too long” ("слишком длинный список аргументов") с очень большим CGO_LDFLAGS.

Trace

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

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

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

Компилятор

Накладные расходы на сборку с Profile Guided Optimization были значительно сокращены. Ранее большие сборки могли увидеть увеличение времени сборки на 100%+ при включении PGO. В Go 1.23 накладные расходы должны быть в однозначных процентах.

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

Для 386 и amd64 компилятор будет использовать информацию из PGO для выравнивания определенных горячих блоков в циклах. Это повышает производительность еще на 1-1,5% за счет дополнительных 0,1% размера текста и двоичного кода. В настоящее время это реализовано только на 386 и amd64, поскольку не показало улучшения на других платформах. Выравнивание горячих блоков можно отключить с помощью -gcflags=[<packages>=]-d=alignhot=0.

Компоновщик

Теперь компоновщик запрещает использовать директиву //go:linkname для ссылки на внутренние символы в стандартной библиотеке (включая среду выполнения), которые не отмечены //go:linkname в своих определениях. Аналогично компоновщик запрещает ссылки на такие символы из ассемблерного кода. Для обратной совместимости существующие использования //go:linkname, найденные в большом количестве открытого исходного кода, остаются поддерживаемыми. Любые новые ссылки на внутренние символы стандартной библиотеки будут запрещены.

Флаг командной строки компоновщика -checklinkname=0 можно использовать для отключения этой проверки в целях отладки и экспериментирования.

При сборке динамически связанного двоичного файла ELF (включая двоичный файл PIE) новый флаг -bindnow включает немедленное связывание функций.

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

Изменения таймера

Go 1.23 вносит два существенных изменения в реализацию time.Timer и time.Ticker.

Во-первых, таймеры и тикеры, на которые больше не ссылается программа, немедленно становятся доступными для сборки мусора, даже если их методы Stop не были вызваны. Более ранние версии Go не собирали неостановленные таймеры до тех пор, пока они не сработают, и никогда не собирали неостановленные тикеры.

Во-вторых, канал таймера, связанный с таймером или тикером, теперь не буферизован, с емкостью 0. Основной эффект этого изменения заключается в том, что Go теперь гарантирует, что для любого вызова метода Reset или Stop никакие устаревшие значения, подготовленные до этого вызова, не будут отправлены или получены после вызова. Более ранние версии Go использовали каналы с одноэлементным буфером, что затрудняло правильное использование Reset и Stop. Видимым эффектом этого изменения является то, что len и cap каналов таймера теперь возвращают 0 вместо 1, что может повлиять на программы, которые опрашивают длину, чтобы решить, будет ли прием на канале таймера успешным. Такой код должен использовать неблокируемый прием вместо этого.

Эти новые поведения включаются только тогда, когда основная программа Go находится в модуле со строкой go в go.mod, использующей Go 1.23.0 или более позднюю версию. Когда Go 1.23 собирает старые программы, старые поведения остаются в силе. Новая настройка GODEBUG asynctimerchan=1 может использоваться для возврата к асинхронному поведению канала, даже если программа называет Go 1.23.0 или более позднюю версию в своем файле go.mod.

Новый пакет unique

Новый пакет unique предоставляет возможности для канонизации значений (например, "интернирование" или "хэш-консинг").

Любое значение сопоставимого типа может быть канонизировано с помощью новой функции Make[T], которая создает ссылку на каноническую копию значения в форме Handle[T]. Два Handle[T] равны тогда и только тогда, когда значения, используемые для создания дескрипторов, равны, что позволяет программам дедуплицировать значения и уменьшать свой объем памяти. Сравнение двух значений Handle[T] эффективно, сводясь к простому сравнению указателей.

Итераторы

Новый пакет iter предоставляет основные определения для работы с пользовательскими итераторами.

Пакет slices добавляет несколько функций, которые работают с итераторами:

  • All возвращает итератор по индексам и значениям среза.
  • Values возвращает итератор по элементам среза.
  • Backward возвращает итератор, который проходит по срезу в обратном направлении.
  • Collect собирает значения из итератора в новый срез.
  • AppendSeq добавляет значения из итератора в существующий срез.
  • Sorted собирает значения из итератора в новый срез, а затем сортирует срез.
  • SortedFunc похож на Sorted, но с функцией сравнения.
  • SortedStableFunc похож на SortFunc, но использует стабильный алгоритм сортировки.
  • Chunk возвращает итератор по последовательным подсрезам до n элементов среза.

Пакет maps добавляет несколько функций, которые работают с итераторами:

  • All возвращает итератор по парам ключ-значение из карты.
  • Keys возвращает итератор по ключам в карте.
  • Values возвращает итератор по значениям в карте.
  • Insert добавляет пары ключ-значение из итератора в существующую карту.
  • Collect собирает пары ключ-значение из итератора в новую карту и возвращает ее.

Новый пакет structs

Новый пакет structs предоставляет типы для полей структур, которые изменяют свойства содержащего типа структуры, такие как макет памяти.

В этом релизе единственным таким типом является HostLayout, который указывает, что структура с полем этого типа имеет макет, который соответствует ожиданиям платформы хоста. HostLayout следует использовать в типах, которые передаются, возвращаются или доступны через указатель, переданный в/из API хоста. Без этого маркера порядок макета структур не гарантируется спецификацией языка, хотя с версии Go 1.23 макеты хоста и языка совпадают.

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

archive/tar

Если аргумент FileInfoHeader реализует новый интерфейс FileInfoNames, то методы интерфейса будут использоваться для установки Uname/Gname заголовка файла. Это позволяет приложениям переопределять зависящий от системы поиск Uname/Gname.

crypto/tls

Клиент TLS теперь поддерживает черновую спецификацию Encrypted Client Hello. Эту функцию можно включить, установив поле Config.EncryptedClientHelloConfigList в закодированный ECHConfigList для хоста, к которому выполняется подключение.

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

Наборы шифров 3DES были удалены из списка по умолчанию, используемого, когда Config.CipherSuites равен нулю. Значение по умолчанию можно вернуть, добавив tls3des=1 в переменную среды GODEBUG.

Экспериментальный постквантовый механизм обмена ключами X25519Kyber768Draft00 теперь включен по умолчанию, когда Config.CurvePreferences равен нулю. Значение по умолчанию можно вернуть, добавив tlskyber=0 в переменную среды GODEBUG.

В версии 1.23 поведение X509KeyPair и LoadX509KeyPair изменено для заполнения поля Certificate.Leaf возвращаемого сертификата. Для этого поведения добавлен новый параметр x509keypairleaf GODEBUG.

crypto/x509

CreateCertificateRequest теперь правильно поддерживает алгоритмы подписи RSA-PSS.

CreateCertificateRequest и CreateRevocationList теперь проверяют сгенерированную подпись с помощью открытого ключа подписчика. Если подпись недействительна, возвращается ошибка. Это поведение CreateCertificate с версии Go 1.16.

Параметр x509sha1 GODEBUG будет удален в следующем основном релизе Go (Go 1.24). Это будет означать, что crypto/x509 больше не будет поддерживать проверку подписей на сертификатах, использующих алгоритмы подписи на основе SHA-1.

Новая функция ParseOID анализирует строку идентификатора объекта ASN.1, закодированную точками. Тип OID теперь реализует интерфейсы encoding.BinaryMarshaler, encoding.BinaryUnmarshaler, encoding.TextMarshaler, encoding.TextUnmarshaler.

database/sql

Ошибки, возвращаемые реализациями driver.Valuer, теперь заключены в оболочку для улучшенной обработки ошибок во время таких операций, как DB.Query, DB.Exec и DB.QueryRow.

debug/elf

Пакет debug/elf теперь определяет PT_OPENBSD_NOBTCFI. Этот ProgType используется для отключения принудительного применения Branch Tracking Control Flow Integrity (BTCFI) в двоичных файлах OpenBSD.

Теперь определяет константы типа символа STT_RELC, STT_SRELC и STT_GNU_IFUNC.

coding/binary

Новые функции Encode и Decode являются эквивалентами байтовых срезов Read и Write. Append позволяет объединять несколько данных в один байтовый срез.

go/ast

Новая функция Preorder возвращает удобный итератор по всем узлам синтаксического дерева.

go/types

Тип Func, представляющий символ функции или метода, теперь имеет метод Func.Signature, который возвращает тип функции, который всегда является Signature.

Тип Alias теперь имеет метод Rhs, который возвращает тип в правой части его объявления: учитывая тип A = B, Rhs A равен B.

Были добавлены методы Alias.Origin, Alias.SetTypeParams, Alias.TypeParams и Alias.TypeArgs. Они необходимы для типов-псевдонимов.

По умолчанию go/types теперь создает узлы типа Alias ​​для псевдонимов типов. Это поведение можно контролировать с помощью флага GODEBUG gotypesalias. Его значение по умолчанию изменилось с 0 в Go 1.22 на 1 в Go 1.23.

math/rand/v2

Были добавлены функция Uint и метод Rand.Uint. Они были непреднамеренно исключены из Go 1.22.

Новый метод ChaCha8.Read реализует интерфейс io.Reader.

net

Новый тип KeepAliveConfig позволяет настраивать параметры поддержки активности для TCP-соединений с помощью нового метода TCPConn.SetKeepAliveConfig и новых полей KeepAliveConfig для Dialer и ListenConfig.

Тип DNSError теперь оборачивает ошибки, вызванные тайм-аутами или отменой. Например, error.Is(someDNSErr, context.DeadlineExceedeed) теперь будет сообщать, была ли ошибка DNS вызвана тайм-аутом.

Новый параметр GODEBUG netedns0=0 отключает отправку дополнительных заголовков EDNS0 в запросах DNS, поскольку, как сообщается, они нарушают работу DNS-сервера на некоторых модемах.

net/http

Cookie теперь сохраняет двойные кавычки вокруг значения cookie. Новое поле Cookie.Quoted указывает, было ли Cookie.Value изначально закавычено.

Новый метод Request.CookiesNamed извлекает все cookie, соответствующие заданному имени.

Новое поле Cookie.Partitioned идентифицирует файлы cookie с атрибутом Partitioned.

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

Новая функция ParseCookie анализирует значение заголовка Cookie и возвращает все файлы cookie, которые были установлены в нем. Поскольку одно и то же имя файла cookie может встречаться несколько раз, возвращаемые значения могут содержать более одного значения для данного ключа.

Новая функция ParseSetCookie анализирует значение заголовка Set-Cookie и возвращает файл cookie. Она возвращает ошибку при синтаксической ошибке.

ServeContent, ServeFile и ServeFileFS теперь удаляют заголовки Cache-Control, Content-Encoding, Etag и Last-Modified при обслуживании ошибки. Эти заголовки обычно применяются к содержимому без ошибок, но не к тексту ошибок.

Промежуточное ПО, которое оборачивает ResponseWriter и применяет кодирование "на лету", например Content-Encoding: gzip, не будет работать после этого изменения. Предыдущее поведение ServeContent, ServeFile и ServeFileFS можно восстановить, установив GODEBUG=httpservecontentkeepheaders=1.

Обратите внимание, что промежуточное ПО, которое изменяет размер обслуживаемого контента (например, сжимая его), уже не работает должным образом, когда ServeContent обрабатывает запрос Range. Сжатие "на лету" должно использовать заголовок Transfer-Encoding вместо Content-Encoding.

Для входящих запросов новое поле Request.Pattern содержит шаблон ServeMux (если есть), который соответствует запросу. Это поле не задается, если задано GODEBUG=httpmuxgo121=1.

net/http/httptest

Новый метод NewRequestWithContext создает входящий запрос с context.Context.

net/netip

В Go 1.22 и более ранних версиях использование reflect.DeepEqual для сравнения Addr, содержащего адрес IPv4, с Addr, содержащим форму IPv6, сопоставленную с IPv4, неправильно возвращало значение true, даже если значения Addr отличались при сравнении с == или Addr.Compare. Теперь эта ошибка исправлена, и все три подхода теперь выдают одинаковый результат.

os

Функция Stat теперь устанавливает бит ModeSocket для файлов, которые являются сокетами Unix в Windows. Эти файлы идентифицируются по тегу повторной обработки, установленному на IO_REPARSE_TAG_AF_UNIX.

В Windows биты режима, сообщаемые Lstat и Stat для точек повторной обработки, изменились. Точки монтирования больше не имеют установленного ModeSymlink, а точки повторной обработки, которые не являются символическими ссылками, сокетами Unix или файлами дедупликации, теперь всегда имеют установленный ModeIrregular. Это поведение контролируется настройкой winsymlink. Для Go 1.23 по умолчанию установлено значение winsymlink=1. Для предыдущих версий по умолчанию установлено значение winsymlink=0.

Функция CopyFS копирует io/fs.FS в локальную файловую систему.

В Windows Readlink больше не пытается нормализовать тома по буквам дисков, что не всегда было возможно. Такое поведение контролируется настройкой winreadlinkvolume. Для Go 1.23 по умолчанию установлено значение winreadlinkvolume=1. Для предыдущих версий по умолчанию установлено значение winreadlinkvolume=0.

В Linux с поддержкой pidfd (обычно Linux v5.4+) функции и методы, связанные с процессами, используют pidfd (а не PID) внутренне, что исключает потенциальное неправильное нацеливание при повторном использовании PID ОС. Поддержка Pidfd полностью прозрачна для пользователя, за исключением дополнительных дескрипторов файлов процессов, которые могут быть у процесса.

path/filepath

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

В Windows EvalSymlinks больше не оценивает точки монтирования, что было источником многих несоответствий и ошибок. Это поведение контролируется настройкой winsymlink. Для Go 1.23 по умолчанию установлено winsymlink=1. В предыдущих версиях по умолчанию установлено winsymlink=0.

В Windows EvalSymlinks больше не пытается нормализовать тома по буквам дисков, что не всегда было возможно. Это поведение контролируется настройкой winreadlinkvolume. Для Go 1.23 по умолчанию установлено winreadlinkvolume=1. В предыдущих версиях по умолчанию установлено winreadlinkvolume=0.

reflect

В Type добавлены новые методы, синонимичные методам с тем же именем в Value:

  • Type.OverflowComplex
  • Type.OverflowFloat
  • Type.OverflowInt
  • Type.OverflowUint

Новая функция SliceAt аналогична NewAt, но для срезов.

Методы Value.Pointer и Value.UnsafePointer теперь поддерживают значения типа String.

Новые методы Value.Seq и Value.Seq2 возвращают последовательности, которые перебирают значение, как если бы оно использовалось в цикле for/range. Новые методы Type.CanSeq и Type.CanSeq2 сообщают, будет ли вызов Value.Seq и Value.Seq2, соответственно, успешным без паники.

runtime/debug

Функция SetCrashOutput позволяет пользователю указать альтернативный файл, в который среда выполнения должна записать свой отчет о фатальном сбое. Его можно использовать для создания автоматизированного механизма отчетности для всех неожиданных сбоев, а не только для тех, которые находятся в goroutines, которые явно используют recovery.

runtime/pprof

Максимальная глубина стека для профилей alloc, mutex, block, threadcreate и goroutine была увеличена с 32 до 128 кадров.

runtime/trace

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

slices

Функция Repeat возвращает новый срез, который повторяет предоставленный срез указанное количество раз.

sync

Метод Map.Clear удаляет все записи, в результате чего получается пустая карта. Он аналогичен clear.

sync/atomic

Новые операторы And и Or применяют побитовое И или ИЛИ к заданным входным данным, возвращая старое значение.

syscall

Пакет syscall теперь определяет WSAENOPROTOOPT в Windows.

Функция GetsockoptInt теперь поддерживается в Windows.

testing/fstest

TestFS теперь возвращает структурированную ошибку, которую можно развернуть (с помощью метода Unwrap() []error). Это позволяет проверять ошибки с помощью error.Is или error.As.

text/template

Теперь шаблоны поддерживают новое действие "else with", что снижает сложность шаблона в некоторых случаях использования.

time

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

unicode/utf16

Функция RuneLen возвращает количество 16-битных слов в кодировке UTF-16 руны. Она возвращает -1, если руна не является допустимым значением для кодировки в UTF-16.

Порты

Darwin

Как было объявлено в примечаниях к выпуску Go 1.22, Go 1.23 требует macOS 11 Big Sur или более поздней версии; поддержка предыдущих версий прекращена.

Linux

Go 1.23 — последний релиз, требующий версию ядра Linux 2.6.32 или более позднюю. Go 1.24 потребует версию ядра Linux 3.17 или более позднюю, за исключением того, что системы под управлением 3.10 или более поздней версии будут по-прежнему поддерживаться, если ядро было исправлено для поддержки системного вызова getrandom.

OpenBSD

Go 1.23 добавляет экспериментальную поддержку OpenBSD на 64-битном RISC-V (GOOS=openbsd, GOARCH=riscv64).

ARM64

Go 1.23 вводит новую переменную среды GOARM64, которая указывает минимальную целевую версию архитектуры ARM64 во время компиляции. Допустимые значения: v8.{0-9} и v9.{0-5}. За этим может следовать параметр, указывающий расширения, реализованные целевым оборудованием. Допустимые параметры: ,lse и ,crypto.

Переменная среды GOARM64 по умолчанию — v8.0.

RISC-V

В Go 1.23 представлена новая переменная среды GORISCV64, которая выбирает профиль приложения пользовательского режима RISC-V для компиляции. Допустимые значения: rva20u64 и rva22u64.

Переменная среды GORISCV64 по умолчанию — rva20u64.

Wasm

Скрипт go_wasip1_wasm_exec в GOROOT/misc/wasm прекратил поддержку версий wasmtime < 14.0.0.


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


пятница, 17 мая 2024 г.

Релиз Go 1.22

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

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

Go 1.22 вносит два изменения в циклы for.

  • Раньше переменные, объявленные в цикле for, создавались один раз и обновлялись на каждой итерации. В Go 1.22 каждая итерация цикла создает новые переменные, чтобы избежать случайных ошибок совместного использования. Инструменты поддержки перехода, описанные в предложении, продолжают работать так же, как и в Go 1.21.
  • Циклы for теперь могут охватывать целые числа. Например:

    package main
    
    import "fmt"
    
    func main() {
      for i := range 10 {
        fmt.Println(10 - i)
      }
      fmt.Println("go1.22 has lift-off!")
    }
    

Go 1.22 включает предварительный просмотр изменения языка, которое рассматриваются для будущей версии Go: итераторы диапазона по функции. Сборка с использованием GOEXPERIMENT=rangefunc включает эту функцию.

Инструменты

Команда go

Команды в рабочих областях теперь могут использовать каталог vendor, содержащий зависимости рабочей области. Каталог создается go work vendor и используется командами сборки, когда для флага -mod установлено значение vendor, что является значением по умолчанию, когда присутствует каталог vendor рабочей области.

Обратите внимание, что содержимое каталога vendor для рабочей области отличается от содержимого каталога отдельного модуля: если каталог в корне рабочей области также содержит один из модулей в рабочей области, его каталог vendor может содержать зависимости либо рабочей области, либо модуль, но не оба.

go get больше не поддерживается за пределами модуля в устаревшем режиме GOPATH (то есть с GO111MODULE=off). Другие команды сборки, такие как go build и go test, будут продолжать работать в устаревших программах GOPATH в течение неопределенного времени.

go mod init больше не пытается импортировать требования к модулям из файлов конфигурации для других инструментов поставщиков (таких как Gopkg.lock).

go test -cover теперь печатает сводные данные о покрытии для покрываемых пакетов, у которых нет собственных тестовых файлов. До версии Go 1.22 при запуске go test -cover для такого пакета выдавалось сообщение
? mymod/mypack [no test files]
и теперь с Go 1.22 функции в пакете считаются непокрытыми:
mymod/mypack coverage: 0.0% of statements

? mymod/mypack [no test files]

Обратите внимание: если пакет вообще не содержит исполняемого кода, мы не можем сообщить о значимом проценте покрытия; для таких пакетов инструмент go будет продолжать сообщать об отсутствии тестовых файлов.

Команды go build, вызывающие компоновщик, теперь выдают ошибку, если будет использоваться внешний (C) компоновщик, но cgo не включен. (Среде выполнения Go требуется поддержка cgo, чтобы гарантировать ее совместимость с любыми дополнительными библиотеками, добавленными компоновщиком C.)

Trace

Веб-интерфейс инструмента трассировки был слегка обновлен в рамках работы по поддержке нового средства трассировки, что позволило решить несколько проблем и улучшить читаемость различных подстраниц. Веб-интерфейс теперь поддерживает изучение трассировок в поточно-ориентированном представлении. Средство просмотра трассировки теперь также отображает полную продолжительность всех системных вызовов.

Эти улучшения применимы только для просмотра трассировок, созданных программами, созданными на Go 1.22 или новее. В будущем релизе некоторые из этих улучшений будут внесены в трассировки, создаваемые старой версией Go.

Go Vet

Ссылки на переменные цикла

Поведение инструмента vet изменилось, чтобы соответствовать новой семантике переменных цикла в Go 1.22. При анализе файла, для которого требуется Go 1.22 или новее (из-за файла go.mod или ограничения сборки для каждого файла), vet больше не сообщает о ссылках на переменные цикла внутри функционального литерала, которые могут пережить итерацию цикла. В Go 1.22 переменные цикла создаются заново для каждой итерации, поэтому такие ссылки больше не подвергаются риску использования переменной после ее обновления циклом.

Новые предупреждения об отсутствующих значениях после append

Инструмент vet теперь сообщает о вызовах append, которые не передают никаких значений для добавления к срезу, например slice = append(slice). Такое выражение не имеет никакого эффекта, и опыт показывает, что это почти всегда ошибка.

Новые предупреждения об отсрочке (defer) time.Since.

Инструмент vet теперь сообщает о неотложенном вызове time.Since(t) внутри оператора defer. Это эквивалентно вызову time.Now().Sub(t) перед оператором defer, а не при вызове отложенной функции. Почти во всех случаях правильный код требует отсрочки вызова time.Since. Например:

t := time.Now()
defer log.Println(time.Since(t)) // неотложенный вызов time.Since
tmp := time.Since(t); defer log.Println(tmp) // эквивалентно предыдущему defer

defer func() {
  log.Println(time.Since(t)) // корректно отложенный вызов time.Since
}()

Новые предупреждения о несовпадающих парах ключ-значение в вызовах log/slog.

Инструмент vet теперь сообщает о недопустимых аргументах при вызовах функций и методов в пакете структурированного журналирования log/slog, который принимает чередующиеся пары ключ/значение. Он сообщает о вызовах, в которых аргумент в ключевой позиции не является ни строкой, ни slog.Attr, и где в конечном ключе отсутствует свое значение.

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

Среда выполнения теперь хранит метаданные сборки мусора на основе типов ближе к каждому объекту кучи, улучшая производительность ЦП (задержку или пропускную способность) программ Go на 1–3%. Это изменение также снижает затраты памяти большинства программ Go примерно на 1% за счет дедупликации избыточных метаданных. В некоторых программах улучшение может быть меньшим, поскольку это изменение корректирует границы класса размера распределителя памяти, поэтому некоторые объекты могут быть перемещены на класс размера выше.

Следствием этого изменения является то, что адреса некоторых объектов, которые раньше всегда были выровнены по границе 16 байт (или выше), теперь будут выровнены только по границе 8 байт. Некоторые программы, использующие инструкции ассемблера, требующие, чтобы адреса памяти были выровнены по размеру более 8 байт и полагаются на предыдущее поведение выравнивания распределителя памяти, могут выйти из строя, но ожидается, что такие программы будут редкими. Такие программы могут быть созданы с использованием GOEXPERIMENT=noallocheaders, чтобы вернуться к старому макету метаданных и восстановить предыдущее поведение выравнивания, но владельцам пакетов следует обновить свой ассемблерный код, чтобы избежать предположения о выравнивании, поскольку этот обходной путь будет удален в будущем релизе.

В порте windows/amd64 программы, связывающие или загружающие библиотеки Go, созданные с помощью -buildmode=c-archive или -buildmode=c-shared, теперь могут использовать функцию SetUnhandledExceptionFilter Win32 для перехвата исключений, не обрабатываемых средой выполнения Go. Обратите внимание, что это уже поддерживалось в порте Windows/386.

Компилятор

Сборки оптимизации на основе профилей (PGO) теперь могут девиртуализировать большую часть вызовов, чем это было возможно ранее. Большинство программ из репрезентативного набора программ Go теперь видят улучшение во время выполнения от 2 до 14% от включения PGO.

Компилятор теперь чередует девиртуализацию и встраивание, поэтому вызовы методов интерфейса лучше оптимизированы.

Go 1.22 также включает предварительную версию расширенной реализации фазы встраивания компилятора, которая использует эвристику для повышения встраиваемости на местах вызовов, которые считаются "важными" (например, в циклах), и препятствует встраиванию на местах вызовов, которые считаются "неважными" (например, на пути паники). Сборка с использованием GOEXPERIMENT=newinliner позволяет использовать новую эвристику места вызова.

Линкер

Флаги -s и -w компоновщика теперь ведут себя более согласованно на всех платформах. Флаг -w подавляет генерацию отладочной информации DWARF. Флаг -s подавляет создание таблицы символов. Флаг -s также подразумевает флаг -w, который можно отменить с помощью -w=0. То есть -s -w=0 создаст двоичный файл с отладочной информацией DWARF, но без таблицы символов.

На платформах ELF флаг компоновщика -B теперь принимает специальную форму: с -B gobuildid компоновщик будет генерировать идентификатор сборки GNU (примечание ELF NT_GNU_BUILD_ID), полученный из идентификатора сборки Go.

В Windows при сборке с параметром -linkmode=internal компоновщик теперь сохраняет информацию SEH из объектных файлов C, копируя разделы .pdata и .xdata в окончательный двоичный файл. Это помогает при отладке и профилировании двоичных файлов с использованием собственных инструментов, таких как WinDbg. Обратите внимание, что до сих пор обработчики исключений SEH функций C не учитывались, поэтому это изменение может привести к тому, что некоторые программы будут вести себя по-другому. -linkmode=external это изменение не затрагивает, поскольку внешние компоновщики уже сохраняют информацию SEH.

Бутстрап

Как упоминалось в примечаниях к релизу Go 1.20, Go 1.22 теперь требует финальной версии Go 1.20 или новее для начальной загрузки. Ожидается, что Go 1.24 потребует финальной версии Go 1.22 или более поздней версии для начальной загрузки.

Основная библиотека

Новый пакет math/rand/v2

Go 1.22 включает первый пакет "v2" стандартной библиотеки — math/rand/v2. Наиболее важные изменения:

  • Метод Read, устаревший в math/rand, не был перенесен в math/rand/v2. (Он остается доступным в math/rand.) Подавляющее большинство вызовов Read должны использовать вместо этого Read crypto/rand. В противном случае можно создать пользовательский Read с использованием метода Uint64.
  • Глобальный генератор, к которому обращаются функции верхнего уровня, заполняется безусловно случайным образом. Поскольку API не гарантирует фиксированной последовательности результатов, теперь возможны такие оптимизации, как состояния генератора случайных чисел для каждого потока.
  • Интерфейс Source теперь имеет единственный метод Uint64; нет интерфейса Source64.
  • Многие методы теперь используют более быстрые алгоритмы, которые невозможно было применить в math/rand, поскольку они изменили выходные потоки.
  • Функции и методы верхнего уровня Intn, Int31, Int31n, Int63 и Int64n из math/rand в math/rand/v2 пишутся более идиоматично: IntN, Int32, Int32N, Int64 и Int64N. Также появились новые функции и методы верхнего уровня Uint32, Uint32N, Uint64, Uint64N, Uint и UintN.
  • Новая универсальная функция N похожа на Int64N или Uint64N, но работает для любого целочисленного типа. Например, случайная длительность от 0 до 5 минут равна rand.N(5*time.Minute).
  • Генератор LFSR Mitchell & Reeds, предоставленный math/rand Source, был заменен двумя более современными источниками псевдослучайного генератора: ChaCha8 и PCG. ChaCha8 — это новый, криптостойкий генератор случайных чисел, по эффективности примерно аналогичный PCG. ChaCha8 — это алгоритм, используемый для функций верхнего уровня в math/rand/v2. Начиная с Go 1.22, функции верхнего уровня math/rand (если они не заданы явно) и среда выполнения Go также используют ChaCha8 для случайности.

Планируется включить инструмент миграции API в будущую версию, скорее всего, в Go 1.23.

Новый пакет go/version

Новый пакет go/version реализует функции для проверки и сравнения строк версии Go.

Улучшенные шаблоны маршрутизации

HTTP-маршрутизация в стандартной библиотеке стала более выразительной. Шаблоны, используемые net/http.ServeMux, были улучшены и теперь принимают методы и подстановочные знаки.

Регистрация обработчика с помощью метода, например "POST/items/create", ограничивает вызовы обработчика запросами с данным методом. Шаблон с методом имеет приоритет над совпадающим шаблоном без него. В частном случае регистрация обработчика с помощью "GET" также регистрирует его с помощью "HEAD".

Подстановочные знаки в шаблонах, например /items/{id}, соответствуют сегментам URL-пути. Доступ к фактическому значению сегмента можно получить, вызвав метод Request.PathValue. Подстановочный знак, оканчивающийся на "...", например /files/{path...}, должен находиться в конце шаблона и соответствовать всем остальным сегментам.

Шаблон, оканчивающийся на "/", как всегда, соответствует всем путям, в которых он есть в качестве префикса. Чтобы точно соответствовать шаблону, включая косую черту, завершите его {$}, как в /exact/match/{$}.

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

Это изменение нарушает обратную совместимость в некоторых аспектах, некоторые из которых очевидны — шаблоны с "{" и "}" ведут себя по-другому, а некоторые — в меньшей степени — улучшена обработка экранированных путей. Изменение контролируется полем GODEBUG с именем httpmuxgo121. Установите httpmuxgo121=1, чтобы восстановить старое поведение.

Небольшие изменения в библиотеке

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

archive/tar

Новый метод Writer.AddFS добавляет в архив все файлы из fs.FS.

archive/zip

Новый метод Writer.AddFS добавляет в архив все файлы из fs.FS.

bufio

Когда SplitFunc возвращает ErrFinalToken с нулевым токеном, Scanner немедленно останавливается. Раньше перед остановкой он сообщал об окончательном пустом токене, что обычно было нежелательно. Вызывающие, которые хотят сообщить об окончательном пустом токене, могут сделать это, вернув []byte{}, а не nil.

cmp

Новая функция Or возвращает первое значение в последовательности, которое не является нулевым значением.

crypto/tls

ConnectionState.ExportKeyingMaterial теперь будет возвращать ошибку, если не используется TLS 1.3 или расширение Extended_master_secret не поддерживается как сервером, так и клиентом. crypto/tls поддерживает это расширение начиная с Go 1.20. Это можно отключить с помощью параметра tlsunsafeekm=1 GODEBUG.

По умолчанию минимальной версией, предлагаемой серверами crypto/tls, теперь является TLS 1.2, если она не указана в config.MinimumVersion, что соответствует поведению клиентов crypto/tls. Это изменение можно отменить с помощью параметра tls10server=1 GODEBUG.

По умолчанию наборы шифров без поддержки ECDHE больше не предлагаются ни клиентами, ни серверами во время рукопожатий до TLS 1.3. Это изменение можно отменить с помощью настройки tlsrsakex=1 GODEBUG.

crypto/x509

Новый метод CertPool.AddCertWithConstraint можно использовать для добавления настраиваемых ограничений к корневым сертификатам, которые будут применяться во время построения цепочки.

В Android корневые сертификаты теперь будут загружаться из /data/misc/keychain/certs-added, а также из /system/etc/security/cacerts.

Новый тип OID поддерживает идентификаторы объектов ASN.1 с отдельными компонентами длиной более 31 бита. Новое поле, использующее этот тип, Policies, добавляется в структуру сертификата и теперь заполняется во время анализа. Любые OID, которые невозможно представить с помощью asn1.ObjectIdentifier, появятся в политиках, но не в старом поле PolicyIdentifiers. При вызове CreateCertificate поле Policies игнорируется, а политики берутся из поля PolicyIdentifiers. Использование параметра x509usepolicies=1 GODEBUG инвертирует это, заполняя политики сертификатов из поля Policies и игнорируя поле PolicyIdentifiers. Возможно изменение значения по умолчанию для x509usepolicies в Go 1.23, которое сделает Policies полем по умолчанию для маршалинга.

database/sql

Новый тип Null[T] предоставляет возможность сканирования столбцов, допускающих значение NULL, на предмет любых типов столбцов.

debug/elf

Константа R_MIPS_PC32 определена для использования с системами MIPS64.

Дополнительные константы R_LARCH_* определены для использования с системами LoongArch.

encoding

Новые методы AppendEncode и AppendDecode, добавленные к каждому из типов кодирования в пакетах  encoding/base32, encoding/base64 и encoding/hex, упрощают кодирование и декодирование из и в байтовые срезы, заботясь об управлении буфером байтовых срезов.

Методы base32.Encoding.WithPadding и base64.Encoding.WithPadding теперь вызывают панику, если аргумент заполнения имеет отрицательное значение, отличное от NoPadding.

encoding/json

Функции маршалинга и кодирования теперь экранируют символы '\b' и '\f' как \b и \f вместо \u0008 и \u000c.

go/ast

Следующие объявления, связанные с разрешением синтаксических идентификаторов, теперь устарели: Ident.Obj, Object, Scope, File.Scope, File.Unresolved, Importer, Package, NewPackage. В общем, идентификаторы не могут быть точно определены без информации о типе. Рассмотрим, например, идентификатор K в T{K: ""}: это может быть имя локальной переменной, если T является типом карты, или именем поля, если T является типом структуры. Новые программы должны использовать пакет go/types для разрешения идентификаторов.

Новая функция ast.Unparen удаляет из выражения все закрывающие круглые скобки.

go/types

Новый тип Alias представляет псевдонимы типов. Раньше псевдонимы типов не представлялись явно, поэтому ссылка на псевдоним типа была эквивалентна указанию псевдонима типа, и имя псевдонима терялось. Новое представление сохраняет промежуточный псевдоним. Это позволяет улучшить отчеты об ошибках (можно сообщить имя псевдонима типа) и позволяет лучше обрабатывать объявления циклических типов, включающие псевдонимы типов. В будущем выпуске типы псевдонимов также будут содержать информацию о параметрах типа. Новая функция Unalias возвращает фактический тип, обозначенный типом Alias (или любым другим типом, если на то пошло).

Поскольку типы псевдонимов могут нарушить работу существующих переключателей типов, которые не умеют их проверять, эта функциональность контролируется полем GODEBUG с именем gotypesalias. Если gotypesalias=0, все работает как прежде, и типы псевдонимов никогда не создаются. Если gotypesalias=1, создаются типы псевдонимов, и клиенты должны их ожидать. По умолчанию используется gotypesalias=0. В будущем релизе значение по умолчанию будет изменено на gotypesalias=1. Клиентам go/types настоятельно рекомендуется как можно скорее скорректировать свой код для работы с gotypesalias=1, чтобы устранить проблемы на раннем этапе.

Структура Info теперь экспортирует карту FileVersions, которая предоставляет информацию о версии Go для каждого файла.

Новый вспомогательный метод PkgNameOf возвращает имя локального пакета для данного объявления импорта.

Реализация SizesFor была скорректирована для вычисления тех же размеров типов, что и компилятор, когда аргументом компилятора SizesFor является "gc". Реализация Sizes по умолчанию, используемая средством проверки типов, теперь имеет вид Types.SizesFor("gc", "amd64").

Начальная позиция (Pos) блока лексического окружения (Scope), представляющего тело функции, изменилась: раньше она начиналась с открывающей фигурной скобки тела функции, но теперь начинается с функционального токена функции.

html/template

Литералы шаблонов Javascript теперь могут содержать действия шаблона Go, а анализ шаблона, содержащего такие действия, больше не будет возвращать ErrJSTemplate. Аналогично, параметр jstmpllitinterp в GODEBUG больше не имеет никакого эффекта.

io

Новый метод SectionReader.Outer возвращает ReaderAt, смещение и размер, переданные в NewSectionReader.

log/slog

Новая функция SetLogLoggerLevel контролирует уровень моста между пакетами `slog` и `log`. Он устанавливает минимальный уровень для вызовов функций ведения журнала `slog` верхнего уровня, а также устанавливает уровень для вызовов `log.Logger`, которые проходят через `slog`.

math/big

Новый метод Rat.FloatPrec вычисляет количество дробных десятичных цифр, необходимых для точного представления рационального числа в виде числа с плавающей запятой, а также определяет, возможно ли вообще точное десятичное представление.

net

Когда io.Copy копирует из TCPConn в UnixConn, он теперь будет использовать системный вызов Linux splice(2), если это возможно, используя новый метод TCPConn.WriteTo.

DNS-резольвер Go, используемый при сборке с "-tags=netgo", теперь ищет соответствующее имя в файле хостов Windows, расположенном по адресу %SystemRoot%\System32\drivers\etc\hosts, перед выполнением DNS-запроса.

net/http

Новые функции ServeFileFS, FileServerFS и NewFileTransportFS являются версиями существующих ServeFile, FileServer и NewFileTransport, работающих на fs.FS.

HTTP-сервер и клиент теперь отклоняют запросы и ответы, содержащие недопустимый пустой заголовок Content-Length. Предыдущее поведение можно восстановить, установив поле GODEBUG httplaxcontentlength=1.

Новый метод Request.PathValue возвращает значения подстановочных знаков пути из запроса, а новый метод Request.SetPathValue устанавливает значения подстановочных знаков пути в запросе.

net/http/cgi

При выполнении процесса CGI переменной PATH_INFO теперь всегда присваивается пустая строка или значение, начинающееся с символа /, как того требует RFC 3875. Ранее для некоторых комбинаций Handler.Root и URL-адреса запроса было возможно нарушить это требование.

net/netip

Новый метод AddrPort.Compare сравнивает два AddrPort.

os

В Windows функция Stat теперь следует за всеми точками повторной обработки, которые ссылаются на другой именованный объект в системе. Раньше он следовал только за точками повторной обработки IO_REPARSE_TAG_SYMLINK и IO_REPARSE_TAG_MOUNT_POINT.

В Windows передача O_SYNC в OpenFile теперь приводит к тому, что операции записи передаются непосредственно на диск, что эквивалентно O_SYNC на платформах Unix.

В Windows функции ReadDir, File.ReadDir, File.Readdir и File.Readdirnames теперь считывают записи каталога в пакетном режиме, чтобы сократить количество системных вызовов, повышая производительность до 30%.

Когда io.Copy копирует из файла в net.UnixConn, он теперь будет использовать системный вызов Linux sendfile(2), если это возможно, используя новый метод File.WriteTo.

os/exec

В Windows LookPath теперь игнорирует пустые записи в %PATH% и возвращает ErrNotFound (вместо ErrNotExist), если не найдено расширение исполняемого файла для разрешения однозначного имени.

В Windows Command и Cmd.Start больше не вызывают LookPath, если путь к исполняемому файлу уже является абсолютным и имеет расширение исполняемого файла. Кроме того, Cmd.Start больше не записывает разрешенное расширение обратно в поле Path, поэтому теперь можно безопасно вызывать метод String одновременно с вызовом Start.

reflect

Метод Value.IsZero теперь возвращает true для числа с плавающей запятой или комплексного отрицательного нуля, а также возвращает true для значения структуры, если пустое поле (поле с именем _) каким-то образом имеет ненулевое значение. Эти изменения делают IsZero совместимым со сравнением значения с нулем с помощью оператора языка ==.

Функция PtrTo устарела в пользу PointerTo.

Новая функция TypeFor возвращает Type, который представляет аргумент типа T. Раньше, чтобы получить значение Reflect.Type для типа, нужно было использовать Reflect.TypeOf((*T)(nil)).Elem(). Теперь это можно записать как reflect.TypeFor[T]().

runtime/metrics

Четыре новых показателя гистограммы /sched/pauses/stopping/gc:seconds, /sched/pauses/stopping/other:seconds, /sched/pauses/total/gc:seconds и /sched/pauses/total/other:seconds предоставляют дополнительные подробности о паузах, связанных с остановкой мира. Метрики "остановки" сообщают о времени, прошедшем от принятия решения об остановке мира до остановки всех горутин. "Общие" показатели сообщают о времени, прошедшем от принятия решения остановить мир до его повторного запуска.

Метрика /gc/pauses:seconds устарела, поскольку она эквивалентна новой метрике /sched/pauses/total/gc:seconds.

/sync/mutex/wait/total:seconds теперь включают в себя конфликты по внутренним блокировкам времени выполнения в дополнение к sync.Mutex и sync.RWMutex.

runtime/pprof

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

Профили мьютексов теперь также включают конкуренцию за внутренние блокировки во время выполнения в дополнение к sync.Mutex и sync.RWMutex. Конфликт по внутренним блокировкам во время выполнения всегда сообщается во время runtime._LostContendedRuntimeLock. В будущих версиях в этих случаях будут добавлены полные трассировки стека.

Профили ЦП на платформах Darwin теперь содержат карту памяти процесса, что позволяет просматривать дизассемблирование в инструменте pprof.

runtime/trace

В этом выпуске трассировщик выполнения был полностью переработан, что решило несколько давних проблем и открыло путь для новых вариантов использования трассировки выполнения.

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

Чтобы разработчики Go могли воспользоваться этими улучшениями, по адресу golang.org/x/exp/trace доступен экспериментальный пакет для чтения трассировки. Обратите внимание, что этот пакет работает только с трассировками, созданными программами, созданными на данный момент с помощью Go 1.22.

Если у вас возникнут какие-либо проблемы с новой реализацией трассировщика выполнения, вы можете вернуться к старой реализации, создав программу Go с GOEXPERIMENT=noexectracer2. Если да, сообщите о проблеме, иначе эта опция будет удалена в будущем релизе.

slices

Новая функция Concat объединяет несколько срезов.

Функции, уменьшающие размер среза (Delete, DeleteFunc, Compact, CompactFunc и Replace), теперь обнуляют элементы между новой длиной и старой длиной.

Команда Insert теперь всегда вызывает панику, если аргумент i выходит за пределы допустимого диапазона. Раньше в этой ситуации не паниковало, если не было элементов для вставки.

syscall

Пакет системных вызовов был заморожен начиная с Go 1.4 и помечен как устаревший в Go 1.11, из-за чего многие редакторы предупреждают о любом использовании пакета. Однако для некоторых неустаревших функций требуется использование пакета syscall, например поля os/exec.Cmd.SysProcAttr. Чтобы избежать ненужных жалоб на такой код, пакет syscall больше не помечается как устаревший. Пакет остается замороженным для большинства новых функций, и в новом коде по-прежнему рекомендуется использовать golang.org/x/sys/unix или golang.org/x/sys/windows, где это возможно.

В Linux новое поле SysProcAttr.PidFD позволяет получить PID FD при запуске дочернего процесса через StartProcess или os/exec.

В Windows передача O_SYNC в Open теперь приводит к тому, что операции записи передаются непосредственно на диск, что эквивалентно O_SYNC на платформах Unix.

testing/slogtest

Новая функция Run использует подтесты для запуска тестовых случаев, обеспечивая более детальный контроль.

Порты

Darwin

В macOS на 64-битной архитектуре x86 (порт darwin/amd64) набор инструментов Go теперь по умолчанию генерирует позиционно-независимые исполняемые файлы (PIE). Двоичные файлы, отличные от PIE, можно создать, указав флаг сборки -buildmode=exe. В 64-битной macOS на базе ARM (порт darwin/arm64) набор инструментов Go уже генерирует PIE по умолчанию.

Go 1.22 — последний релиз, который будет работать на macOS 10.15 Catalina. Для Go 1.23 потребуется macOS 11 Big Sur или более поздняя версия.

Arm

Переменная среды GOARM теперь позволяет вам выбирать, использовать ли программную или аппаратную плавающую запятую. Раньше допустимыми значениями GOARM были 5, 6 или 7. Теперь за этими же значениями можно опционально следовать ,softfloat или ,hardfloat для выбора реализации с плавающей запятой.

Эта новая опция по умолчанию имеет мягкое плавание для версии 5 и жесткое плавание для версий 6 и 7.

Loong64

Порт loong64 теперь поддерживает передачу аргументов функции и результатов с использованием регистров.

Порт linux/loong64 теперь поддерживает очистку адресов, очистку памяти, перемещение компоновщика нового стиля и режим сборки плагинов.

OpenBSD

В Go 1.22 добавлен экспериментальный порт OpenBSD на 64-битном PowerPC с прямым порядком байтов (openbsd/ppc64).


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