Примечания к выпуску Go 1.17
Введение в Go 1.17
Последний выпуск Go, версия 1.17, появился через шесть месяцев после Go 1.16. Большинство изменений касаются реализации инструментария, среды выполнения и библиотек. Как и всегда, выпуск сохраняет обещание совместимости Go 1. Ожидается, что почти все программы на Go будут продолжать компилироваться и запускаться так же, как и раньше.
Изменения в языке
Go 1.17 включает три небольших улучшения в языке.
-
Преобразования
из среза в указатель на массив: Выражение
sтипа[]Tтеперь может быть преобразовано в тип указателя на массив*[N]T. Еслиa— результат такого преобразования, то соответствующие индексы, которые находятся в диапазоне, ссылаются на одни и те же базовые элементы:&a[i] == &s[i]для0 <= i < N. Преобразование вызывает панику, еслиlen(s)меньше, чемN. -
unsafe.Add:unsafe.Add(ptr, len)добавляетlenкptrи возвращает обновленный указательunsafe.Pointer(uintptr(ptr) + uintptr(len)). -
unsafe.Slice: Для выраженияptrтипа*T,unsafe.Slice(ptr, len)возвращает срез типа[]T, чей базовый массив начинается сptr, а его длина и вместимость равныlen.
Улучшения в пакете unsafe были добавлены для упрощения написания кода, соответствующего
правилам безопасности unsafe.Pointer,
но сами правила остались без изменений. В частности, существующие
программы, корректно использующие unsafe.Pointer, остаются
валидными, а новые программы должны по-прежнему следовать этим правилам при
использовании unsafe.Add или unsafe.Slice.
Обратите внимание, что новое преобразование из среза в указатель на массив — это первый случай, когда преобразование типа может вызвать панику во время выполнения. Инструменты анализа, предполагающие, что преобразования типов никогда не могут вызвать панику, должны быть обновлены, чтобы учесть эту возможность.
Платформы
Darwin
Как сообщалось в примечаниях к выпуску Go 1.16, Go 1.17 требует macOS 10.13 High Sierra или новее; поддержка предыдущих версий была прекращена.
Windows
Go 1.17 добавляет поддержку 64-битной архитектуры ARM на Windows (порт
windows/arm64). Этот порт поддерживает cgo.
OpenBSD
64-битная архитектура MIPS на OpenBSD (порт openbsd/mips64)
теперь поддерживает cgo.
В Go 1.16 на 64-битных архитектурах x86 и 64-битной ARM на
OpenBSD (порты openbsd/amd64 и openbsd/arm64)
системные вызовы выполняются через libc, а не напрямую с использованием машинных инструкций.
В Go 1.17 это также реализовано на 32-битных архитектурах x86 и 32-битной ARM на OpenBSD
(порты openbsd/386 и openbsd/arm).
Это обеспечивает совместимость с OpenBSD 6.9 и новее, которые требуют
выполнять системные вызовы через libc для нестатических
бинарных файлов Go.
ARM64
Программы на Go теперь сохраняют указатели кадров стека на 64-битной архитектуре ARM на всех операционных системах. Ранее указатели кадров стека были включены только на Linux, macOS и iOS.
Зарезервированное значение GOARCH для loong64
Основной компилятор Go пока не поддерживает архитектуру LoongArch,
но мы зарезервировали значение GOARCH
«loong64».
Это означает, что файлы Go с именем *_loong64.go будут теперь
игнорироваться инструментами Go,
кроме случаев, когда используется это значение GOARCH.
Инструменты
Команда go
Сокращённые графы модулей в go 1.17
Если модуль указывает go 1.17 или выше, граф модулей включает только непосредственные зависимости других модулей go 1.17, а не полные транзитивные зависимости. (См. Сокращение графа модулей для более подробной информации.)
Для того чтобы команда go корректно разрешала транзитивные импорты, используя сокращённый граф модулей, файл go.mod каждого модуля должен содержать больше информации о транзитивных зависимостях, относящихся к этому модулю. Если модуль указывает go 1.17 или выше в своём файле go.mod, его файл go.mod теперь содержит явную require-директиву для каждого модуля, предоставляющего транзитивно импортируемый пакет. (В предыдущих версиях файл go.mod обычно содержал только явные требования для непосредственно импортируемых пакетов.)
Поскольку расширенный файл go.mod, необходимый для сокращения графа модулей, включает все зависимости, необходимые для загрузки импортов любого пакета в основном модуле, если основной модуль указывает go 1.17 или выше, инструмент go больше не читает (и даже не скачивает) файлы go.mod для зависимостей, если они не требуются для выполнения запрошенной команды.
(См. Ленивая загрузка.)
Поскольку количество явных требований может быть значительно больше в расширенном файле Go 1.17 go.mod, вновь добавленные требования к непрямым зависимостям в модуле go 1.17 теперь хранятся в отдельном блоке require, отличном от блока, содержащего прямые зависимости.
Для облегчения перехода к сокращённым графам модулей в Go 1.17, подкоманда
go mod tidy
теперь поддерживает флаг -go для установки или изменения версии go в файле go.mod. Чтобы преобразовать файл go.mod существующего модуля в Go 1.17 без изменения выбранных версий его зависимостей, выполните:
<code> go mod tidy -go=1.17 </code>
По умолчанию go mod tidy проверяет, что выбранные версии зависимостей, относящихся к основному модулю, совпадают с версиями, которые использовались бы в предыдущем релизе Go (Go 1.16 для модуля, указывающего go 1.17), и сохраняет записи в go.sum, необходимые для этого релиза, даже для зависимостей, которые обычно не требуются другими командами.
Флаг -compat позволяет переопределить эту версию для поддержки более старых (или только более новых) версий, до версии, указанной директивой go в файле go.mod. Чтобы привести модуль go 1.17 к состоянию для Go 1.17 без сохранения контрольных сумм (или проверки соответствия) с Go 1.16:
<code> go mod tidy -compat=1.17 </code>
Обратите внимание, что даже если основной модуль был приведён в порядок с помощью -compat=1.17, пользователи, которые require этот модуль из модуля go 1.16 или более ранней версии, всё ещё смогут его использовать, при условии, что пакеты используют только совместимые языковые и библиотечные возможности.
Подкоманда go mod graph
также поддерживает флаг -go, который заставляет её отображать граф,
видимый для указанной версии Go, показывая зависимости, которые иначе могут быть удалены.
Комментарии об устаревших модулях
Авторы модулей могут объявить модуль устаревшим, добавив
// Deprecated:
комментарий в файл go.mod, а затем создав новую версию.
Команда go get теперь выводит предупреждение, если модуль,
необходимый для сборки пакетов, указанных в командной строке, является устаревшим.
Команда go list -m -u выводит
информацию об устаревших зависимостях для всех зависимостей (используйте -f или
-json, чтобы увидеть полное сообщение). Команда go рассматривает
разные основные версии как отдельные модули, поэтому этот механизм может использоваться,
например, для предоставления пользователям инструкций по миграции на новую основную версию.
go get
Флаг go get -insecure устарел и был удалён.
Чтобы разрешить использование небезопасных схем при получении зависимостей,
пожалуйста, используйте переменную окружения GOINSECURE.
Флаг -insecure также обходил проверку сумм модулей, используйте
GOPRIVATE или GONOSUMDB, если вам нужна эта функциональность.
См. go help environment для получения подробностей.
Команда go get выводит предупреждение об устаревании при установке
команд вне основного модуля (без флага -d).
Вместо этого следует использовать go install cmd@version
для установки команды в конкретной версии, используя суффикс, например,
@latest или @v1.2.3. В Go 1.18 флаг -d всегда будет включён,
и go get будет использоваться только для изменения зависимостей в go.mod.
Файлы go.mod без директив go
Если в файле go.mod основного модуля отсутствует
go директива и команда go
не может обновить файл go.mod, то команда go теперь предполагает
go 1.11 вместо текущего релиза. (go mod init
автоматически добавлял go директивы начиная с Go 1.12.)
Если у зависимости модуля отсутствует явный файл go.mod или
файл go.mod не содержит
go директивы,
команда go теперь предполагает go 1.16 для этой зависимости
вместо текущего релиза. (Зависимости, разрабатываемые в режиме GOPATH, могут не иметь файла go.mod,
и файл vendor/modules.txt до сих пор не записывал версии go,
указанные в файлах go.mod зависимостей.)
Содержимое vendor
Если основной модуль указывает go 1.17 или выше,
go mod vendor
теперь аннотирует vendor/modules.txt версией go, указанной в каждом
внедрённом модуле в его собственном файле go.mod. Эта аннотированная версия
используется при сборке пакетов модуля из исходного кода, находящегося в vendor.
Если основной модуль указывает go 1.17 или выше,
go mod vendor теперь исключает файлы go.mod
и go.sum для внедрённых зависимостей, которые иначе могут мешать команде go
определять правильный корень модуля при вызове внутри дерева vendor.
Подсказки паролей
Команда go по умолчанию теперь подавляет запросы SSH-паролей и запросы Git Credential Manager при получении Git-репозиториев с использованием SSH, как это уже было ранее реализовано для других запросов паролей Git. Пользователи, проходящие аутентификацию в частных Git-репозиториях с паролем защищённого SSH, могут настроить ssh-agent для того, чтобы команда go могла использовать защищённые паролем SSH-ключи.
go mod download
Когда команда go mod download вызывается без аргументов, она больше не сохраняет контрольные суммы для загруженного содержимого модулей в go.sum. Тем не менее, она может вносить изменения в go.mod и go.sum, необходимые для загрузки списка сборки. Это соответствует поведению Go 1.15. Чтобы сохранить контрольные суммы для всех модулей, используйте команду go mod download all.
//go:build инструкции
Команда go теперь понимает //go:build инструкции и предпочитает их // +build инструкциям. Новый синтаксис использует булевы выражения, как и Go, и должен быть менее подвержен ошибкам. Начиная с этого релиза, новый синтаксис полностью поддерживается, и все файлы Go должны быть обновлены так, чтобы содержали оба варианта с одинаковым смыслом. Для облегчения миграции, gofmt теперь автоматически синхронизирует оба варианта. За дополнительной информацией о синтаксисе и плане миграции обращайтесь к
https://golang.org/design/draft-gobuild.
go run
Команда go run теперь принимает аргументы с суффиксами версий (например, go run
example.com/cmd@v1.0.0). Это заставляет команду go run собирать и запускать пакеты в режиме, осведомлённом о модулях, игнорируя файл go.mod в текущем каталоге или любом родительском каталоге, если такой имеется. Это полезно для запуска исполняемых файлов без их установки или изменения зависимостей текущего модуля.
Gofmt
gofmt (и go fmt) теперь синхронизирует //go:build инструкции с // +build инструкциями. Если файл содержит только // +build инструкции, они будут перемещены в соответствующее место в файле, и будут добавлены соответствующие //go:build инструкции. В противном случае, // +build инструкции будут перезаписаны на основе существующих //go:build инструкций. За дополнительной информацией обращайтесь к
https://golang.org/design/draft-gobuild.
Vet
Новое предупреждение о несоответствии //go:build и // +build инструкций
Инструмент vet теперь проверяет, что //go:build и // +build инструкции находятся в правильной части файла и синхронизированы между собой. Если они не совпадают,
gofmt может быть использован для их исправления. За дополнительной информацией обращайтесь к
https://golang.org/design/draft-gobuild.
Новое предупреждение о вызове signal.Notify на не буферизованных каналах
Инструмент vet теперь предупреждает о вызовах signal.Notify с входящими сигналами, отправляемыми на не буферизованный канал. Использование не буферизованного канала может привести к потере сигналов, так как signal.Notify не блокируется при отправке в канал. Например:
<code>c := make(chan os.Signal) // signals are sent on c before the channel is read from. // This signal may be dropped as c is unbuffered. signal.Notify(c, os.Interrupt) </code>
Пользователи signal.Notify должны использовать каналы с достаточным объёмом буфера, чтобы справляться с ожидаемым количеством сигналов.
Новые предупреждения для методов Is, As и Unwrap
Инструмент vet теперь выдает предупреждения о методах с именами As, Is или Unwrap,
реализующих интерфейс error, сигнатура которых отличается от ожидаемой пакетом errors.
Функции errors.{As,Is,Unwrap} ожидают, что такие методы реализуют либо Is(error) bool,
либо As(interface{}) bool, либо Unwrap() error соответственно.
Функции errors.{As,Is,Unwrap} будут игнорировать методы с такими же именами, но другой сигнатурой.
Например:
<code>type MyError struct { hint string }
func (m MyError) Error() string { ... } // MyError implements error.
func (MyError) Is(target interface{}) bool { ... } // target is interface{} instead of error.
func Foo() bool {
x, y := MyError{"A"}, MyError{"B"}
return errors.Is(x, y) // returns false as x != y and MyError does not have an `Is(error) bool` function.
}
</code>
Cover
Инструмент cover теперь использует оптимизированный парсер из golang.org/x/tools/cover,
что может заметно ускорить парсинг больших профилей покрытия.
Компилятор
Go 1.17 реализует новый способ передачи аргументов и результатов функций с использованием регистров вместо стека.
Бенчмарки для репрезентативного набора пакетов и программ показывают повышение производительности примерно на 5% и типичное уменьшение размера бинарного файла примерно на 2%.
Это в настоящее время включено для Linux, macOS и Windows на 64-битной архитектуре x86 (порт linux/amd64,
darwin/amd64 и windows/amd64).
Это изменение не влияет на функциональность любого безопасного Go-кода и разработано так, чтобы не иметь никакого влияния на большинство ассемблерных функций.
Оно может повлиять на код, который нарушает правила unsafe.Pointer
при доступе к аргументам функции или зависит от недокументированного поведения, связанного с сравнением указателей на код функции.
Для обеспечения совместимости с существующими ассемблерными функциями компилятор генерирует адаптерные функции, которые конвертируют между новым соглашением вызова на основе регистров и предыдущим стековым соглашением.
Эти адаптеры обычно не видны пользователям, за исключением случаев, когда берется адрес Go-функции в ассемблерном коде или адрес ассемблерной функции в Go-коде
с использованием reflect.ValueOf(fn).Pointer() или unsafe.Pointer,
в этом случае теперь будет возвращаться адрес адаптера.
Код, который зависит от значения этих указателей на код, может больше не вести себя ожидаемым образом.
Адаптеры также могут вызвать незначительное снижение производительности в двух случаях:
непрямой вызов ассемблерной функции из Go через значение func и вызов Go-функций из ассемблера.
Формат трассировок стека из среды выполнения (выводимых при возникновении необработанного панического состояния или при вызове runtime.Stack) улучшен.
Ранее аргументы функций выводились как шестнадцатеричные слова, основанные на макете памяти.
Теперь каждый аргумент в исходном коде выводится отдельно, разделённый запятыми.
Агрегатные типы (struct, array, string, slice, interface и complex) аргументы разделяются фигурными скобками.
Однако стоит учитывать, что значение аргумента, который существует только в регистре и не сохранён в память, может быть неточным.
Значения возвращаемых функций (которые обычно были неточными) больше не выводятся.
Функции, содержащие замыкания, теперь могут быть встроены.
Одним из последствий этого изменения является то, что функция с замыканием может
создавать уникальный указатель замыкания для каждого места, где функция встраивается.
Значения Go-функций не сравнимы напрямую, но это изменение
может выявить ошибки в коде, который использует reflect
или unsafe.Pointer для обхода этого языкового ограничения и сравнения функций по указателю кода.
Компоновщик
Когда компоновщик использует внешний режим компоновки, который является значением по умолчанию при компоновке программы, использующей cgo, и компоновщик вызывается с опцией -I, то эта опция теперь будет передана внешнему компоновщику как опция -Wl,--dynamic-linker.
Стандартная библиотека
Cgo
Пакет runtime/cgo теперь предоставляет новую возможность, позволяющую преобразовывать любые значения Go в безопасное представление, которое может быть использовано для безопасной передачи значений между C и Go. Подробнее см. в runtime/cgo.Handle.
Разбор URL-запросов
Пакеты net/url и net/http ранее принимали ";" (точка с запятой) как разделитель параметров в URL-запросах, в дополнение к "&" (амперсанд). Сейчас параметры с незакодированными точками с запятой отвергаются, и серверы net/http будут записывать предупреждение в Server.ErrorLog при обнаружении такого параметра в URL-запросе.
Например, до Go 1.17 метод Query URL example?a=1;b=2&c=3 возвращал map[a:[1] b:[2] c:[3]], тогда как теперь он возвращает map[c:[3]].
При обнаружении такого строки запроса, URL.Query и Request.FormValue игнорируют параметры, содержащие точку с запятой, ParseQuery возвращает оставшиеся параметры и ошибку, а Request.ParseForm и Request.ParseMultipartForm возвращают ошибку, но всё же устанавливают поля Request на основе оставшихся параметров.
Пользователи net/http могут восстановить оригинальное поведение, используя новый обёртку обработчика AllowQuerySemicolons. Это также подавит предупреждение в ErrorLog. Следует отметить, что принятие точек с запятой как разделителей запросов может привести к проблемам безопасности, если различные системы интерпретируют ключи кэширования по-разному. Подробнее см. issue 25192.
Строгий ALPN для TLS
Когда Config.NextProtos установлен, серверы теперь проверяют наличие пересечения между настроенными протоколами и протоколами ALPN, объявленными клиентом (если таковые имеются). Если нет общего поддерживаемого протокола, соединение закрывается с оповещением no_application_protocol, как требуется RFC 7301. Это помогает смягчить атаку ALPACA межпротокольного типа.
Как исключение, когда значение "h2" включено в Config.NextProtos сервера, клиенты HTTP/1.1 будут допущены к подключению, как если бы они не поддерживали ALPN.
См. issue 46310 для дополнительной информации.
Мелкие изменения в библиотеке
Как обычно, в библиотеке были внесены различные мелкие изменения и обновления, сделанные с учётом обещания совместимости Go 1.
archive/zip
Новые методы File.OpenRaw, Writer.CreateRaw, Writer.Copy обеспечивают поддержку случаев, где производительность является основным фактором.
bufio
Метод Writer.WriteRune теперь записывает символ замены U+FFFD для отрицательных значений рун, как и для других недопустимых рун.
bytes
Метод Buffer.WriteRune теперь записывает символ замены U+FFFD для отрицательных значений рун, как и для других недопустимых рун.
compress/lzw
Функция NewReader теперь гарантированно возвращает значение нового типа Reader, аналогично функции NewWriter, которая гарантированно возвращает значение нового типа Writer.
Оба новых типа реализуют метод Reset (Reader.Reset, Writer.Reset), что позволяет повторно использовать Reader или Writer.
crypto/ed25519
Пакет crypto/ed25519 был переписан, и все операции теперь примерно в два раза быстрее на amd64 и arm64.
Наблюдаемое поведение не изменилось.
crypto/elliptic
Методы CurveParams теперь автоматически вызывают более быструю и безопасную специализированную реализацию для известных кривых (P-224, P-256 и P-521), если такая реализация доступна. Обратите внимание, что это подход наилучших усилий, и приложениям следует избегать использования универсальных, не константно-временных методов CurveParams, а вместо этого использовать специализированные реализации Curve, такие как P256.
Реализация кривой P521 была переписана с использованием кода, сгенерированного проектом fiat-crypto, который основан на формально верифицированной модели арифметических операций. Теперь реализация константно-временная и в три раза быстрее на amd64 и arm64. Наблюдаемое поведение не изменилось.
crypto/rand
Пакет crypto/rand теперь использует системный вызов getentropy в macOS и системный вызов getrandom в Solaris, Illumos и DragonFlyBSD.
crypto/tls
Новый метод Conn.HandshakeContext позволяет пользователю контролировать отмену текущего TLS-рукопожатия. Предоставленный контекст доступен из различных обратных вызовов через новые методы ClientHelloInfo.Context и CertificateRequestInfo.Context. Отмена контекста после завершения рукопожатия не имеет никакого эффекта.
Сортировка наборов шифров теперь полностью обрабатывается пакетом crypto/tls. В настоящее время наборы шифров сортируются по уровню безопасности, производительности и поддержке аппаратного обеспечения, учитывая как локальное, так и удалённое оборудование. Порядок поля Config.CipherSuites теперь игнорируется, а также поле Config.PreferServerCipherSuites. Обратите внимание, что Config.CipherSuites по-прежнему позволяет приложениям выбирать, какие наборы шифров TLS 1.0–1.2 будут включены.
Наборы шифров 3DES были перемещены в
InsecureCipherSuites
из-за фундаментального слабого места, связанного с размером блока. Они по-прежнему включены по умолчанию, но только в качестве последнего средства, благодаря изменению порядка наборов шифров, описанному выше.
Начиная с следующего релиза, Go 1.18, значение по умолчанию для
Config.MinVersion
в crypto/tls будет TLS 1.2, что отключит TLS 1.0 и TLS 1.1 по умолчанию. Приложения смогут переопределить это изменение, явно установив Config.MinVersion.
Это не повлияет на crypto/tls серверы.
crypto/x509
CreateCertificate
теперь возвращает ошибку, если предоставленный закрытый ключ не соответствует открытому ключу родителя (если он есть). Полученный сертификат не смог бы пройти проверку.
Временный флаг GODEBUG=x509ignoreCN=0 был удалён.
ParseCertificate
был переписан и теперь использует на ~70% меньше ресурсов. Наблюдаемое поведение при обработке сертификатов WebPKI не изменилось, за исключением сообщений об ошибках.
В системах BSD теперь осуществляется поиск доверенных корневых сертификатов в /etc/ssl/certs. Это добавляет поддержку нового системного хранилища доверенных сертификатов в FreeBSD 12.2+.
Начиная с следующего релиза, Go 1.18, crypto/x509 будет отклонять сертификаты, подписанные с использованием хэш-функции SHA-1. Это не относится к самоподписанным корневым сертификатам. Практические атаки против SHA-1
были продемонстрированы в 2017 году, а публичные удостоверяющие центры больше не выпускали сертификаты с SHA-1 с 2015 года.
database/sql
Метод DB.Close теперь закрывает поле connector, если тип этого поля реализует интерфейс
io.Closer.
Новые структуры
NullInt16
и
NullByte
представляют значения int16 и byte, которые могут быть null. Их можно использовать как цели метода Scan, аналогично NullString.
debug/elf
Добавлена константа SHT_MIPS_ABIFLAGS.
encoding/binary
binary.Uvarint прекращает чтение после 10 байт для предотвращения потерь вычислений. Если требуется больше 10 байт, возвращаемое количество байт будет -11.
В предыдущих версиях Go могли возвращаться большие отрицательные значения при чтении некорректно закодированных varint.
encoding/csv
Новый метод
Reader.FieldPos
возвращает номер строки и столбца, соответствующие началу заданного поля в записи, последней возвращённой методом
Read.
encoding/xml
Когда комментарий появляется внутри
Directive, он теперь заменяется на один пробел вместо того, чтобы полностью исключаться.
Недопустимые имена элементов или атрибутов с ведущими, завершающими или множественными двоеточиями теперь сохраняются без изменений в поле
Name.Local.
flag
Объявления флагов теперь вызывают панику, если указано недопустимое имя.
go/build
Новое поле
Context.ToolTags
хранит теги сборки, соответствующие текущей конфигурации инструментария Go.
go/format
Функции Source и
Node теперь
синхронизируют строки //go:build с строками // +build.
Если файл содержит только строки // +build, они будут перемещены в соответствующее место в файле, и будут добавлены соответствующие строки //go:build.
В противном случае, строки // +build будут перезаписаны на основе существующих строк //go:build.
За дополнительной информацией обращайтесь к
https://golang.org/design/draft-gobuild.
go/parser
Новое значение Mode SkipObjectResolution
инструктирует парсер не разрешать идентификаторы до их объявления.
Это может повысить скорость парсинга.
image
Конкретные типы изображений (RGBA, Gray16 и так далее)
теперь реализуют новый интерфейс RGBA64Image.
Конкретные типы, которые ранее реализовывали интерфейс
draw.Image, теперь также реализуют
draw.RGBA64Image, новый интерфейс в пакете image/draw.
io/fs
Новая функция FileInfoToDirEntry преобразует FileInfo в DirEntry.
math
Пакет math теперь определяет три дополнительных константы: MaxUint, MaxInt и MinInt.
Для 32-битных систем их значения соответственно равны 2^32 - 1, 2^31 - 1 и -2^31.
Для 64-битных систем их значения соответственно равны 2^64 - 1, 2^63 - 1 и -2^63.
mime
В системах Unix таблица MIME-типов теперь читается из локальной системы Shared MIME-info Database, если она доступна.
mime/multipart
Part.FileName
теперь применяет
filepath.Base к возвращаемому значению.
Это снижает потенциальные уязвимости в приложениях, принимающих multipart-сообщения, такие как net/http-серверы, вызывающие
Request.FormFile.
net
Новый метод IP.IsPrivate сообщает, является ли адрес
частным IPv4-адресом согласно RFC 1918
или локальным IPv6-адресом согласно RFC 4193.
Разрешитель DNS в Go теперь отправляет только один DNS-запрос при разрешении адреса для сети, поддерживающей только IPv4 или только IPv6, вместо того чтобы запрашивать обе адресные семейства.
Сентинельная ошибка ErrClosed и
тип ошибки ParseError теперь реализуют
интерфейс net.Error.
Функции ParseIP и ParseCIDR
теперь отвергают IPv4-адреса, содержащие десятичные компоненты с ведущими нулями.
Эти компоненты всегда интерпретировались как десятичные, но некоторые операционные системы трактуют их как восьмеричные.
Это несоответствие теоретически может привести к проблемам безопасности, если Go-приложение используется для проверки IP-адресов,
которые затем используются в их оригинальной форме в других приложениях, интерпретирующих компоненты как восьмеричные. Как правило,
рекомендуется всегда перешифровывать значения после проверки, что позволяет избежать подобных проблем с несоответствием парсеров.
net/http
Пакет net/http теперь использует новый
(*tls.Conn).HandshakeContext
с контекстом Request
при выполнении TLS-рукопожатий на клиенте или сервере.
Установка полей Server
ReadTimeout или WriteTimeout в отрицательное значение теперь означает отсутствие таймаута,
а не немедленный таймаут.
Функция ReadRequest
теперь возвращает ошибку, если запрос содержит несколько заголовков Host.
При создании перенаправления на очищенную версию URL,
ServeMux теперь всегда
использует относительные URL в заголовке Location. Ранее он
возвращал полный URL запроса, что могло привести к непреднамеренным
перенаправлениям, если клиент мог отправить абсолютный URL-запрос.
При интерпретации определённых HTTP-заголовков, обрабатываемых net/http,
непечатные символы теперь игнорируются или отвергаются.
Если
Request.ParseForm
возвращает ошибку при вызове из
Request.ParseMultipartForm,
последняя теперь продолжает заполнять
Request.MultipartForm
перед тем, как вернуть его.
net/http/httptest
ResponseRecorder.WriteHeader
теперь вызывает панику, если предоставленный код не является корректным трёхзначным HTTP-статусом.
Это соответствует поведению реализаций ResponseWriter
в пакете net/http.
net/url
Новый метод Values.Has
сообщает, установлен ли параметр запроса.
os
Метод File.WriteString был оптимизирован таким образом, чтобы не создавать копию входной строки.
reflect
Новый метод Value.CanConvert сообщает, можно ли преобразовать значение к заданному типу.
Это может быть использовано для избежания паники при преобразовании среза в указатель на массив, если срез слишком короткий.
Ранее для этого достаточно было использовать Type.ConvertibleTo,
но новое разрешенное преобразование из среза в указатель на массив может вызвать панику даже в том случае, если типы допустимы для преобразования.
Новые методы StructField.IsExported
и Method.IsExported сообщают, является ли поле структуры или метод типа экспортируемым.
Они предоставляют более читаемую альтернативу проверке пустого значения PkgPath.
Новая функция VisibleFields возвращает все видимые поля в типе структуры, включая поля внутри анонимных членов структуры.
Функция ArrayOf теперь вызывает панику при передаче отрицательной длины.
Проверка метода Type.ConvertibleTo больше не гарантирует, что вызов Value.Convert не вызовет панику.
Он может вызвать панику при преобразовании `[]T` в `*[N]T`, если длина среза меньше N.
См. раздел изменения языка выше.
Методы Value.Convert и
Type.ConvertibleTo были исправлены таким образом, чтобы не рассматривать типы из разных пакетов с одинаковыми именами как идентичные, чтобы соответствовать разрешению языка.
runtime/metrics
Добавлены новые метрики, отслеживающие общее количество выделенных и освобожденных байтов и объектов. Также добавлена новая метрика, отслеживающая распределение задержек планирования горутин.
runtime/pprof
Профили блокировок больше не смещены в пользу редких долгих событий перед частыми короткими.
strconv
Пакет strconv теперь использует алгоритм Ryū Ульфа Адамса для форматирования чисел с плавающей точкой.
Этот алгоритм улучшает производительность на большинстве входных данных и более чем на 99% быстрее на худших входных данных.
Новая функция QuotedPrefix возвращает кавычную строку (как понимает Unquote),
расположенную в начале входных данных.
strings
Метод Builder.WriteRune теперь записывает символ замены U+FFFD для отрицательных значений руны,
как это делается для других недопустимых рун.
sync/atomic
atomic.Value теперь имеет методы Swap и
CompareAndSwap, предоставляющие дополнительные атомарные операции.
syscall
Функции GetQueuedCompletionStatus и
PostQueuedCompletionStatus
устарели. У этих функций некорректные сигнатуры, и они заменены эквивалентами в пакете
golang.org/x/sys/windows.
В системах, совместимых с Unix, теперь группа процессов дочернего процесса устанавливается с заблокированными сигналами.
Это предотвращает отправку сигнала SIGTTOU дочернему процессу, если родитель находится в фоновой группе процессов.
Версия SysProcAttr для Windows имеет два новых поля. AdditionalInheritedHandles — это список дополнительных дескрипторов, которые будут унаследованы новым дочерним процессом.
ParentProcess позволяет указать родительский процесс нового процесса.
Константа MSG_CMSG_CLOEXEC теперь определена на системах DragonFly и всех системах OpenBSD (она уже была определена на некоторых системах OpenBSD и на всех системах FreeBSD, NetBSD и Linux).
Константы SYS_WAIT6 и WEXITED теперь определены на системах NetBSD (SYS_WAIT6 уже был определён на системах DragonFly и FreeBSD;
WEXITED уже был определён на системах Darwin, DragonFly, FreeBSD, Linux и Solaris).
testing
Добавлён новый флаг тестирования -shuffle, который управляет порядком выполнения тестов и бенчмарков.
Новые методы
T.Setenv
и B.Setenv
позволяют устанавливать переменную окружения на время выполнения теста или бенчмарка.
text/template/parse
Новое значение SkipFuncCheck Mode
изменяет парсер шаблонов таким образом, чтобы он не проверял, определены ли функции.
time
Тип Time теперь имеет метод
GoString, который
возвращает более полезное значение при печати с использованием спецификатора формата
%#v из пакета fmt.
Новый метод Time.IsDST может использоваться для проверки, находится ли время в периоде летнего времени в заданном месте.
Новые методы Time.UnixMilli и
Time.UnixMicro
возвращают количество миллисекунд и микросекунд, прошедших с 1 января 1970 года UTC соответственно.
Новые функции UnixMilli и
UnixMicro
возвращают локальное значение Time, соответствующее заданному времени Unix.
Пакет теперь принимает запятую “,” как разделитель дробной части секунды при разборе и форматировании времени. Например, следующие форматы времени теперь принимаются:
- 2006-01-02 15:04:05,999999999 -0700 MST
- Mon Jan _2 15:04:05,000000 2006
- Monday, January 2 15:04:05,000 2006
Новая константа Layout
определяет эталонное время.
unicode
Функции Is,
IsGraphic,
IsLetter,
IsLower,
IsMark,
IsNumber,
IsPrint,
IsPunct,
IsSpace,
IsSymbol и
IsUpper теперь возвращают false для отрицательных значений руны, как и для других недопустимых рун.