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

Введение в Go 1.14

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

Поддержка модулей в команде go теперь готова для продакшн-использования, и мы приглашаем всех пользователей перейти на Go модули для управления зависимостями. Если вы не можете перейти из-за проблемы в инструментарии Go, пожалуйста, убедитесь, что проблема имеет открытую задачу. (Если задача не в里程碑 Go1.15, пожалуйста, сообщите нам, почему она мешает вам перейти, чтобы мы могли правильно приоритизировать её.)

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

Согласно предложению по перекрывающимся интерфейсам, в Go 1.14 теперь разрешено встраивание интерфейсов с перекрывающимися наборами методов: методы встраиваемого интерфейса могут иметь те же имена и идентичные сигнатуры, что и методы, уже существующие в (встраиваемом) интерфейсе. Это решает проблемы, которые обычно (но не обязательно) возникают при использовании диагональных графов встраивания. Явно объявленные методы в интерфейсе должны оставаться уникальными, как и раньше.

Платформы

Darwin

Go 1.14 — последний выпуск, который будет работать на macOS 10.11 El Capitan. Go 1.15 потребует macOS 10.12 Sierra или новее.

Go 1.14 — последний выпуск Go, поддерживающий 32-битные бинарники на macOS (порт darwin/386). Они больше не поддерживаются macOS, начиная с macOS 10.15 (Catalina). Go продолжает поддерживать 64-битный порт darwin/amd64.

Go 1.14, вероятно, будет последним выпуском Go, поддерживающим 32-битные бинарники на iOS, iPadOS, watchOS и tvOS (порт darwin/arm). Go продолжает поддерживать 64-битный порт darwin/arm64.

Windows

Бинарные файлы Go в Windows теперь имеют включённую DEP (предотвращение выполнения данных).

В Windows создание файла через os.OpenFile с флагом os.O_CREATE или через syscall.Open с флагом syscall.O_CREAT теперь будет создавать файл как доступный только для чтения, если бит 0o200 (разрешение на запись владельца) не установлен в аргументе прав. Это делает поведение в Windows более похожим на поведение в Unix-системах.

WebAssembly

Значения JavaScript, на которые ссылается Go через объекты js.Value, теперь могут быть собраны сборщиком мусора.

Значения js.Value больше не могут быть сравнены с помощью оператора ==, а должны сравниваться с помощью их метода Equal.

js.Value теперь имеет методы IsUndefined, IsNull и IsNaN.

RISC-V

Go 1.14 содержит экспериментальную поддержку 64-битного RISC-V на Linux (GOOS=linux, GOARCH=riscv64). Следует учитывать, что производительность, стабильность синтаксиса ассемблера и, возможно, корректность находятся в разработке.

FreeBSD

Go теперь поддерживает 64-битную архитектуру ARM на FreeBSD 12.0 и выше (порт freebsd/arm64).

Native Client (NaCl)

Как сообщалось в заметках о релизе Go 1.13, Go 1.14 прекращает поддержку платформы Native Client (GOOS=nacl).

Illumos

Среда выполнения теперь учитывает ограничения CPU зоны (контроль ресурсов zone.cpu-cap) для runtime.NumCPU и значения по умолчанию параметра GOMAXPROCS.

Инструменты

Команда go

Управление зависимостями (Vendoring)

Когда главный модуль содержит каталог верхнего уровня vendor и его файл go.mod указывает go 1.14 или выше, команда go теперь по умолчанию использует -mod=vendor для операций, которые принимают этот флаг. Новое значение этого флага, -mod=mod, заставляет команду go загружать модули из кэша модулей (как если бы каталога vendor не существовало).

Когда установлен флаг -mod=vendor (явно или по умолчанию), команда go теперь проверяет, что файл vendor/modules.txt главного модуля соответствует его файлу go.mod.

go list -m больше не будет молча пропускать транзитивные зависимости, которые не предоставляют пакеты в каталоге vendor. Теперь она завершается с ошибкой, если установлен флаг -mod=vendor и запрашивается информация о модуле, не упомянутом в vendor/modules.txt.

Флаги

Команда go get больше не принимает флаг -mod. Ранее значение этого флага либо игнорировалось, либо вызывало ошибку сборки.

-mod=readonly теперь устанавливается по умолчанию, когда файл go.mod доступен только для чтения и отсутствует директория vendor на верхнем уровне.

-modcacherw — это новый флаг, который указывает команде go оставлять недавно созданные директории в кэше модулей с их стандартными правами доступа, вместо того чтобы делать их доступными только для чтения. Использование этого флага увеличивает вероятность того, что тесты или другие инструменты случайно добавят файлы, не включенные в проверочную сумму модуля. Однако это позволяет использовать rm -rf (вместо go clean -modcache) для удаления кэша модулей.

-modfile=file — это новый флаг, который указывает команде go читать (и при необходимости записывать) альтернативный файл go.mod вместо того, который находится в корневой директории модуля. Файл с именем go.mod всё ещё должен присутствовать, чтобы определить корневую директорию модуля, но он не будет читаться. Когда указан флаг -modfile, используется также альтернативный файл go.sum: его путь выводится из флага -modfile путём удаления расширения .mod и добавления .sum.

Переменные окружения

GOINSECURE — это новая переменная окружения, которая указывает команде go не требовать HTTPS-подключения и пропускать проверку сертификатов при получении определённых модулей непосредственно из их источников. Как и существующая переменная GOPRIVATE, значение GOINSECURE представляет собой список шаблонов подстановки, разделённых запятыми.

Команды вне модулей

Когда явно включён режим работы с модулями (путём установки GO111MODULE=on), большинство команд, связанных с модулями, имеют ограниченную функциональность, если файл go.mod отсутствует. Например, go build, go run и другие команды сборки могут собирать только пакеты стандартной библиотеки и пакеты, указанные как .go файлы в командной строке.

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

Команда go get продолжает работать как раньше, как и go mod download и go list -m с явно указанной версией.

+incompatible версии

Если последняя версия модуля содержит файл go.mod, команда go get больше не обновит до несовместимой мажорной версии этого модуля, если такая версия не запрашивается явно или уже требуется.

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

Обслуживание файла go.mod

Команды go, отличные от go mod tidy, больше не удаляют директиву require, которая указывает версию косвенной зависимости, которая уже подразумевается другими (транзитивными) зависимостями основного модуля.

Команды go, отличные от go mod tidy, больше не редактируют файл go.mod, если изменения носят только косметический характер.

Когда установлен флаг -mod=readonly, команды go больше не завершатся ошибкой из-за отсутствия директивы go или ошибочного комментария // indirect.

Загрузка модулей

Команда go теперь поддерживает репозитории Subversion в режиме модулей.

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

Тестирование

go test -v теперь потоково передаёт вывод t.Log по мере его появления, а не в конце всех тестов.

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

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

Горутины теперь асинхронно прерываемы. В результате, циклы без вызовов функций больше не могут потенциально заблокировать планировщик или значительно задержать сборку мусора. Эта функция поддерживается на всех платформах, кроме windows/arm, darwin/arm, js/wasm и plan9/*.

В результате реализации прерывания, на Unix-системах, включая Linux и macOS, программы, собранные с использованием Go 1.14 будут получать больше сигналов, чем программы, собранные с предыдущих выпусков. Это означает, что программы, использующие пакеты вроде syscall или golang.org/x/sys/unix будут сталкиваться с большей частотой системных вызовов, завершающихся с ошибкой EINTR. Такие программы должны обрабатывать эти ошибки, наиболее вероятно, путём повторной попытки выполнить системный вызов. За дополнительной информацией об этом см. man 7 signal для систем Linux или аналогичную документацию для других систем.

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

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

Компилятор

В этом релизе добавлена опция компиляции -d=checkptr, которая позволяет добавить инструментирование для проверки соблюдения правил безопасности unsafe.Pointer во время выполнения. Эта опция включена по умолчанию (за исключением Windows) при использовании флагов -race или -msan, и может быть отключена с помощью -gcflags=all=-d=checkptr=0. В частности, -d=checkptr проверяет следующее:

  1. При преобразовании unsafe.Pointer в *T, полученный указатель должен быть правильно выровнен для типа T.
  2. Если результат арифметики указателей указывает на объект в куче Go, один из операндов типа unsafe.Pointer должен указывать на тот же объект.

Использование -d=checkptr в настоящее время не рекомендуется в Windows, поскольку оно вызывает ложные срабатывания в стандартной библиотеке.

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

Детальный анализ утечек памяти (-m=2) снова работает. Эта функция была убрана из новой реализации анализа утечек в предыдущем релизе.

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

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

Удаление проверок границ теперь использует информацию, полученную при создании срезов, и может удалять проверки для индексов с типами меньше, чем int.

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

Новый пакет хеширования последовательностей байтов

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

Хеш-функции устойчивы к коллизиям, но не являются криптографически безопасными.

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

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

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

crypto/tls

Поддержка версии SSL 3.0 (SSLv3) была удалена. Следует отметить, что SSLv3 — это криптографически сломанный протокол, предшествующий TLS.

Отключение TLS 1.3 теперь невозможно через переменную окружения GODEBUG. Вместо этого используйте поле Config.MaxVersion для настройки версий TLS.

Если через поле Config.Certificates предоставляется несколько цепочек сертификатов, то теперь автоматически выбирается первая совместимая с удалённой стороной. Это позволяет, например, предоставить сертификаты ECDSA и RSA и позволить пакету автоматически выбрать лучший. Следует отметить, что производительность такого выбора будет плохой, если не задано поле Certificate.Leaf. Поле Config.NameToCertificate, которое поддерживает сопоставление только одного сертификата с заданным именем, теперь устарело и должно быть установлено в nil. Аналогично, метод Config.BuildNameToCertificate, который строит поле NameToCertificate на основе листовых (leaf) сертификатов, также устарел и не должен вызываться.

Новые функции CipherSuites и InsecureCipherSuites возвращают список текущих реализованных шифровых наборов. Новая функция CipherSuiteName возвращает имя для идентификатора шифрового набора.

Новые методы (*ClientHelloInfo).SupportsCertificate и (*CertificateRequestInfo).SupportsCertificate предоставляют информацию о том, поддерживает ли удалённая сторона определённый сертификат.

Пакет tls больше не поддерживает устаревшее расширение Next Protocol Negotiation (NPN) и теперь поддерживает только ALPN. В предыдущих версиях поддерживались оба. Изменений API нет, и приложения должны работать идентично, как и раньше. Большинство других клиентов и серверов уже удалили поддержку NPN в пользу стандартизованного ALPN.

В TLS 1.2 теперь используются подписи RSA-PSS, если они поддерживаются. Это не повлияет на большинство приложений, но пользовательские реализации Certificate.PrivateKey, которые не поддерживают подписи RSA-PSS, должны использовать новое поле Certificate.SupportedSignatureAlgorithms для их отключения.

Поля Config.Certificates и Config.GetCertificate могут быть равны nil, если задано Config.GetConfigForClient. Если обратные вызовы не возвращают сертификаты и не вызывают ошибку, теперь отправляется unrecognized_name.

Новое поле CertificateRequestInfo.Version предоставляет версию TLS для обратных вызовов клиентских сертификатов.

Новые константы TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256 и TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 используют финальные названия для наборов шифров, ранее называвшихся TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 и TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305.

crypto/x509

Certificate.CreateCRL теперь поддерживает издателей Ed25519.

debug/dwarf

Пакет debug/dwarf теперь поддерживает чтение DWARF версии 5.

Новый метод (*Data).AddSection поддерживает добавление произвольных новых секций DWARF из входного файла в структуру Data DWARF.

Новый метод (*Reader).ByteOrder возвращает порядок байтов текущей единицы компиляции. Это может использоваться для интерпретации атрибутов, закодированных в естественном порядке, таких как описания местоположений.

Новый метод (*LineReader).Files возвращает таблицу имен файлов из читателя строк. Это может использоваться для интерпретации значений атрибутов DWARF, таких как AttrDeclFile.

encoding/asn1

Unmarshal теперь поддерживает строковый тип ASN.1 BMPString, представленный новой константой TagBMPString.

encoding/json

Тип Decoder поддерживает новый метод InputOffset, который возвращает смещение байта входного потока в текущей позиции декодера.

Compact больше не экранирует символы U+2028 и U+2029, что никогда не было документированной особенностью. Для правильного экранирования см. HTMLEscape.

Number больше не принимает недопустимые числа, чтобы следовать документированному поведению более точно. Если программе требуется принимать недопустимые числа, например пустую строку, рассмотрите возможность обёртки типа с помощью Unmarshaler.

Unmarshal теперь может поддерживать ключи карты с типом строки, реализующие encoding.TextUnmarshaler.

go/build

Тип Context имеет новое поле Dir, которое может использоваться для установки рабочей директории для сборки. По умолчанию — текущая директория выполняющегося процесса. В режиме модулей это используется для определения главного модуля.

go/doc

Новая функция NewFromFiles вычисляет документацию пакета из списка *ast.File и связывает примеры с соответствующими элементами пакета. Новая информация доступна в новом поле Examples в типах Package, Type, и Func, а также в новом поле Suffix в типе Example.

io/ioutil

TempDir теперь может создавать директории с предсказуемыми префиксами и суффиксами в именах. Как и TempFile, если шаблон содержит символ «*», случайная строка заменяет последний символ «*».

log

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

math

Новая функция FMA вычисляет x*y+z в формате с плавающей точкой без промежуточного округления вычисления x*y. Несколько архитектур реализуют это вычисление с использованием специализированных инструкций аппаратного обеспечения для дополнительной производительности.

math/big

Метод GCD теперь позволяет использовать входные значения a и b, равные нулю или отрицательные.

math/bits

Новые функции Rem, Rem32 и Rem64 поддерживают вычисление остатка даже в случае переполнения частного.

mime

Тип по умолчанию для файлов .js и .mjs теперь text/javascript вместо application/javascript. Это соответствует черновику IETF, в котором application/javascript считается устаревшим.

mime/multipart

Новый метод Reader NextRawPart поддерживает получение следующей части MIME без прозрачного декодирования данных quoted-printable.

net/http

Новый метод Header Values может использоваться для получения всех значений, связанных с каноническим ключом.

Новое поле Transport DialTLSContext может использоваться для указания необязательной функции подключения для создания TLS-соединений для непроксированных HTTPS-запросов. Это новое поле может использоваться вместо DialTLS, который теперь считается устаревшим; DialTLS продолжит работать, но в новом коде следует использовать DialTLSContext, который позволяет транспорту отменять подключения сразу же после их ненужности.

В Windows ServeFile теперь корректно отдает файлы размером более 2 ГБ.

net/http/httptest

Новое поле Server EnableHTTP2 поддерживает включение HTTP/2 на тестовом сервере.

net/textproto

Новый метод MIMEHeader Values может быть использован для получения всех значений, связанных с канонизированным ключом.

net/url

При неудачном разборе URL (например, с помощью Parse или ParseRequestURI), resulting Error сообщение теперь будет цитировать неразборчивый URL. Это обеспечивает более чёткую структуру и согласованность с другими ошибками разбора.

os/signal

В Windows события CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT и CTRL_SHUTDOWN_EVENT теперь генерируют сигнал syscall.SIGTERM, аналогично тому, как Control-C и Control-Break генерируют сигнал syscall.SIGINT.

plugin

Пакет plugin теперь поддерживает freebsd/amd64.

reflect

StructOf теперь поддерживает создание типов структур с неэкспортируемыми полями, устанавливая поле PkgPath в элементе StructField.

runtime

runtime.Goexit больше не может быть прерван рекурсивным panic/recover.

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

runtime/pprof

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

strconv

Тип NumError теперь имеет метод Unwrap, который может быть использован для получения причины сбоя конвертации. Это позволяет использовать значения NumError с errors.Is, чтобы проверить, является ли базовая ошибка strconv.ErrRange или strconv.ErrSyntax.

sync

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

testing

Пакет testing теперь поддерживает функции очистки, вызываемые после завершения теста или бенчмарка, путем вызова T.Cleanup или B.Cleanup соответственно.

text/template

Пакет text/template теперь корректно сообщает об ошибках, когда заключенный в скобки аргумент используется как функция. Это наиболее часто проявляется в ошибочных случаях, таких как {{if (eq .F "a") or (eq .F "b")}}. Это должно быть написано как {{if or (eq .F "a") (eq .F "b")}}. Ошибочный случай никогда не работал должным образом, и теперь будет сообщаться с ошибкой can't give argument to non-function.

JSEscape теперь эскапирует символы & и = для снижения последствий, если его вывод используется неправильно в HTML-контекстах.

unicode

Пакет unicode и связанная с ним поддержка по всей системе были обновлены с Unicode 11.0 до Unicode 12.0, что добавляет 554 новых символа, включая четыре новых скрипта, и 61 новый эмодзи.

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

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