Примечания к выпуску Go 1.10
Введение в Go 1.10
Последний выпуск Go, версия 1.10, появился через шесть месяцев после Go 1.9. Большая часть изменений касается реализации инструментария, среды выполнения и библиотек. Как и всегда, выпуск сохраняет обещание совместимости Go 1. Ожидается, что почти все программы на Go продолжат компилироваться и выполняться так же, как и раньше.
В этом выпуске улучшено кэширование скомпилированных пакетов,
добавлено кэширование успешных результатов тестов,
выполняется анализ vet автоматически во время тестов,
а также разрешено прямая передача строковых значений между Go и C с использованием cgo.
Новый жёстко заданный набор безопасных параметров компилятора может вызвать
неожиданные ошибки invalid flag в коде, который успешно компилировался с предыдущими версиями.
Изменения в языке
В спецификации языка нет значительных изменений.
Уточнён случай с сдвигами неконкретных констант, в результате чего компиляторы были обновлены для разрешения выражения индекса
x[1.0 << s], где s — беззнаковое целое число;
пакет go/types уже делал это.
Грамматика методов была обновлена для смягчения синтаксических ограничений, позволяя использовать любое выражение типа в качестве получателя;
это соответствует тому, что уже реализовывали компиляторы.
Например, struct{io.Reader}.Read — это корректное, хотя и необычное, выражение метода, которое компиляторы уже принимали, и теперь разрешено грамматикой языка.
Платформы
В этом выпуске не появилось новых поддерживаемых операционных систем или архитектур процессоров. Большая часть работы была направлена на усиление поддержки существующих платформ, особенно новые инструкции в ассемблере и улучшения в коде, генерируемом компиляторами.
Как было объявлено в примечаниях к Go 1.9, Go 1.10 теперь требует FreeBSD 10.3 или новее; поддержка FreeBSD 9.3 была прекращена.
Go снова запускается на NetBSD, но требует ещё не выпущенной версии NetBSD 8.
Поддержка реализована только для GOARCH amd64 и 386.
Порт для arm всё ещё не работает.
В 32-битных системах на MIPS новые настройки переменной среды
GOMIPS=hardfloat (по умолчанию) и
GOMIPS=softfloat позволяют выбрать, использовать ли
аппаратные инструкции или программную эмуляцию для вычислений с плавающей точкой.
Go 1.10 — последний релиз, который будет работать в OpenBSD 6.0. Go 1.11 потребует OpenBSD 6.2.
Go 1.10 — последний релиз, который будет работать в OS X 10.8 Mountain Lion или OS X 10.9 Mavericks. Go 1.11 потребует OS X 10.10 Yosemite или более поздней версии.
Go 1.10 — последний релиз, который будет работать в Windows XP или Windows Vista. Go 1.11 потребует Windows 7 или более поздней версии.
Инструменты
Стандартный GOROOT и GOTMPDIR
Если переменная окружения $GOROOT не установлена,
команда go ранее использовала стандартный GOROOT,
установленный во время компиляции инструментария.
Теперь, прежде чем переключаться на этот стандартный путь, команда go пытается
определить GOROOT на основе собственного пути к исполняемому файлу.
Это позволяет распаковывать бинарные дистрибутивы в любое место файловой системы и использовать их без явной установки переменной GOROOT.
По умолчанию команда go создаёт временные файлы и каталоги
в системном каталоге временных файлов (например, $TMPDIR в Unix).
Если установлена новая переменная окружения $GOTMPDIR,
команда go будет создавать свои временные файлы и каталоги в указанном каталоге.
Сборка и установка
Команда go build теперь определяет устаревшие пакеты
исключительно на основе содержимого исходных файлов, указанных флагов сборки и метаданных, хранящихся в скомпилированных пакетах.
Время модификации больше не учитывается.
Старое рекомендованное решение добавлять -a для принудительной пересборки в случаях,
когда время модификации было недостоверным по какой-либо причине
(например, изменения в флагах сборки) больше не требуется:
сборки теперь всегда определяют, когда пакеты необходимо пересобрать.
(Если вы наблюдаете иное поведение, пожалуйста, сообщите об ошибке.)
Опции go build -asmflags, -gcflags, -gccgoflags и -ldflags
теперь применяются по умолчанию только к пакетам, указанным напрямую в командной строке.
Например, go build -gcflags=-m mypkg
передаёт флаг компилятору -m при сборке mypkg,
но не его зависимости.
Новая, более общая форма -asmflags=pattern=flags (и аналогично для других)
применяет flags только к пакетам, соответствующим шаблону.
Например: go install -ldflags=cmd/gofmt=-X=main.version=1.2.3 cmd/...
устанавливает все команды, соответствующие шаблону cmd/..., но применяет флаг -X
только к флагам линкера для cmd/gofmt.
Для получения дополнительной информации см. go help build.
Команда go build теперь поддерживает кэш
недавно собранных пакетов, отдельно от установленных пакетов в $GOROOT/pkg или $GOPATH/pkg.
Эффект кэширования должен ускорить сборки, которые не устанавливают пакеты явно,
или при переключении между различными копиями исходного кода (например, при переключении между различными ветками в системе контроля версий).
Старое рекомендованное решение использовать флаг -i для ускорения, как в go build -i
или go test -i,
больше не требуется: сборки теперь работают так же быстро без флага -i.
Для получения дополнительной информации см. go help cache.
Команда go install теперь устанавливает только те пакеты и команды, которые указаны непосредственно в командной строке.
Например, go install cmd/gofmt устанавливает программу gofmt, но не устанавливает пакеты, от которых она зависит.
Новый кэш сборки позволяет следующим командам работать так же быстро, как если бы зависимости были установлены.
Чтобы принудительно установить зависимости, используйте новый флаг go install -i.
В общем случае установка зависимостей пакетов не требуется,
и сама концепция установленных пакетов может исчезнуть в будущих релизах.
Множество деталей реализации go build были изменены для поддержки этих улучшений.
Одно из новых требований, вытекающих из этих изменений, заключается в том, что
пакеты, содержащие только бинарные файлы, теперь должны объявлять корректные блоки импорта в их заглушечном исходном коде,
чтобы эти импорты были доступны при связывании программы, использующей такой пакет.
За дополнительными подробностями обращайтесь к go help filetype.
Test
Команда go test теперь кэширует результаты тестов:
если исполняемый файл теста и командная строка совпадают с предыдущим запуском,
а файлы и переменные окружения, использованные в этом запуске,
также не изменились, go test выведет
предыдущий вывод теста, заменив затраченное время строкой “(cached)”.
Кэширование тестов применяется только к успешным результатам;
только к командам go test
с явным списком пакетов; и
только к командным строкам, использующим подмножество флагов
-cpu, -list, -parallel,
-run, -short и -v тестов.
Идиоматический способ обхода кэширования тестов — использовать -count=1.
Команда go test теперь автоматически запускает
go vet для пакета, который тестируется,
чтобы выявить существенные проблемы перед запуском теста.
Любые такие проблемы рассматриваются как ошибки сборки и препятствуют выполнению теста.
Включены только проверки go vet с высокой степенью уверенности
для этой автоматической проверки.
Чтобы отключить запуск go vet, используйте
go test -vet=off.
Флаг go test -coverpkg теперь
интерпретирует свой аргумент как список шаблонов, разделённых запятыми,
для сопоставления с зависимостями каждого теста, а не как список пакетов для повторной загрузки.
Например, go test -coverpkg=all
теперь является осмысленным способом запустить тест с включённым покрытием для тестового пакета
и всех его зависимостей.
Кроме того, опция go test -coverprofile теперь
поддерживается при запуске нескольких тестов.
В случае сбоя из-за превышения времени ожидания, тесты теперь более вероятно записывают свои профили перед завершением.
Команда go test теперь всегда объединяет стандартный вывод и стандартную ошибку выполнения тестовой программы и записывает оба потока в стандартный вывод команды go test. В предыдущих версиях команда go test применяла такое объединение лишь в большинстве случаев.
Вывод команды go test -v теперь включает строки обновления статуса PAUSE и CONT, чтобы отмечать, когда параллельные тесты приостанавливаются и возобновляются.
Новый флаг go test -failfast отключает запуск дополнительных тестов после того, как любой тест завершится неудачей. Следует отметить, что тесты, запущенные параллельно с неудачным тестом, могут завершиться.
Наконец, новый флаг go test -json фильтрует вывод тестов через новую команду go tool test2json, чтобы создать машиночитаемое описание выполнения тестов в формате JSON. Это позволяет создавать богатые представления выполнения тестов в IDE и других инструментах.
Для получения дополнительных сведений обо всех этих изменениях см. go help test и документацию test2json.
Cgo
Опции, указанные cgo с помощью #cgo CFLAGS и аналогичных директив, теперь проверяются по списку разрешённых опций. Это закрывает уязвимость, при которой загруженный пакет использовал опции компилятора, такие как -fplugin, чтобы выполнить произвольный код на машине, где происходит сборка. Это может привести к ошибке сборки, такой как invalid flag in #cgo CFLAGS. Для получения дополнительного контекста и способа обработки этой ошибки см. https://golang.org/s/invalidflag.
Cgo теперь реализует C typedef вида “typedef X Y” с использованием псевдонима типа Go, благодаря чему Go-код может использовать типы C.X и C.Y взаимозаменяемо. Также поддерживается использование макросов, ведущих себя как функции, без аргументов. Кроме того, документация была обновлена для уточнения, что Go-структуры и Go-массивы не поддерживаются в сигнатурах функций, экспортируемых cgo.
Cgo теперь поддерживает прямой доступ к значениям строк Go из C. Функции в предварительной части C могут использовать тип _GoString_ для принятия строки Go в качестве аргумента. C-код может вызывать _GoStringLen и _GoStringPtr для прямого доступа к содержимому строки. Значение типа _GoString_ может быть передано в вызов экспортируемой Go-функции, которая принимает аргумент типа Go string.
Во время начальной загрузки инструментария переменные окружения CC и CC_FOR_TARGET указывают на компилятор C по умолчанию, который будет использоваться создаваемым инструментарием для сборки на хосте и для целевой платформы соответственно. Однако, если инструментарий будет использоваться с несколькими целевыми платформами, может потребоваться указать разные компиляторы C для каждой из них (например, разный компилятор для darwin/arm64 и linux/ppc64le). Новый набор переменных окружения CC_FOR_goos_goarch позволяет указать разный компилятор C по умолчанию для каждой целевой платформы. Следует отметить, что эти переменные применяются только во время начальной загрузки инструментария, чтобы установить значения по умолчанию, используемые создаваемым инструментарием. Позднее команды go build будут использовать переменную окружения CC или встроенные значения по умолчанию.
Теперь Cgo переводит некоторые типы C, которые обычно сопоставлялись с указательным типом в Go, в uintptr вместо этого. Эти типы включают иерархию CFTypeRef в фреймворке CoreFoundation в Darwin и иерархию jobject в интерфейсе JNI в Java.
Эти типы должны быть uintptr со стороны Go, потому что иначе они могли бы запутать сборщик мусора Go; они иногда не являются настоящими указателями, а представляют собой структуры данных, закодированные в целом числовом значении размером с указатель. Указатели на память Go не должны храниться в этих значениях uintptr.
Из-за этого изменения значения затронутых типов необходимо инициализировать нулевым значением с константой 0, а не константой nil. Go 1.10 предоставляет модули gofix, чтобы помочь с этим переписыванием:
<code>go tool fix -r cftype <pkg> go tool fix -r jni <pkg> </code>
Для получения дополнительных сведений см. документацию по cgo.
Doc
Инструмент go doc теперь добавляет функции, возвращающие срезы T или *T, в отображение типа T, подобно уже существующему поведению для функций, возвращающих одиночные T или *T результаты. Например:
<code>$ go doc mail.Address
package mail // import "net/mail"
type Address struct {
Name string
Address string
}
Address represents a single mail address.
func ParseAddress(address string) (*Address, error)
func ParseAddressList(list string) ([]*Address, error)
func (a *Address) String() string
$
</code>
Ранее ParseAddressList отображалась только в обзоре пакета (go doc mail).
Fix
Инструмент go fix теперь заменяет импорты "golang.org/x/net/context" на "context". (Перенаправляющие псевдонимы в предыдущем делают его полностью эквивалентным последнему при использовании Go 1.9 или новее.)
Get
Команда go get теперь поддерживает репозитории исходного кода Fossil.
Pprof
Профили блокировок и мьютексов, создаваемые пакетом runtime/pprof, теперь включают информацию о символах, поэтому их можно просматривать с помощью go tool pprof без двоичного файла, который создал профиль. (Все другие типы профилей были изменены, чтобы включать информацию о символах в Go 1.9.)
Визуализатор профилей go tool pprof был обновлён до git версии 9e20b5b (2017-11-08) из github.com/google/pprof, который включает обновлённый веб-интерфейс.
Vet
Команда go vet теперь всегда имеет доступ к полной и актуальной информации о типах при проверке пакетов, даже для пакетов, использующих cgo или vendored импорты. Отчёты должны стать более точными в результате. Обратите внимание, что только go vet имеет доступ к этой информации; более низкоуровневый go tool vet не имеет и должен использоваться только при разработке самого vet. (Начиная с Go 1.9, go vet предоставляет доступ ко всем тем же флагам, что и go tool vet.)
Диагностика
В этом выпуске добавлен обзор доступных инструментов диагностики программ на Go.
Gofmt
Две небольшие детали форматирования исходного кода Go по умолчанию были изменены.
Во-первых, определённые сложные выражения трёхиндексного среза ранее форматировались как
x[i+1 : j:k], а теперь форматируются с более согласованным интервалом: x[i+1 : j : k].
Во-вторых, литералы интерфейсов с одним методом, записанные в одну строку,
которые иногда используются в утверждениях типа,
больше не разбиваются на несколько строк.
Обратите внимание, что подобные незначительные обновления gofmt являются обычным явлением. В общем, мы рекомендуем не создавать системы, проверяющие, что исходный код соответствует выводу конкретной версии gofmt. Например, тест непрерывной интеграции, который завершается неудачей, если какой-либо код, уже проверенный в репозитории, не отформатирован должным образом, является принципиально хрупким и не рекомендуется.
Если несколько программ должны согласовывать использование определённой версии gofmt для форматирования исходного файла,
рекомендуется организовать это путём вызова одного и того же двоичного файла gofmt.
Например, в открытом репозитории Go, наш Git pre-commit хук написан на Go
и мог бы напрямую импортировать go/format, но вместо этого он вызывает двоичный файл gofmt,
находящийся в текущем пути, чтобы хук не требовал перекомпиляции при каждом изменении gofmt.
Инструментарий компилятора
Компилятор включает множество улучшений производительности сгенерированного кода, распределённых довольно равномерно по поддерживаемым архитектурам.
Информация отладки DWARF, записанная в бинарные файлы, была улучшена несколькими способами: константные значения теперь записываются; информация о номерах строк стала более точной, что улучшает шаги по исходному коду в программе; а каждый пакет теперь представлен как отдельная единица компиляции DWARF.
Различные режимы сборки
были перенесены на большее количество систем.
В частности, c-shared теперь работает на linux/ppc64le, windows/386 и windows/amd64;
pie теперь работает на darwin/amd64 и также принудительно использует внешнюю компоновку на всех системах;
а plugin теперь работает на linux/ppc64le и darwin/amd64.
Порт для linux/ppc64le теперь требует использования внешней компоновки
для всех программ, использующих cgo, даже если это касается стандартной библиотеки.
Ассемблер
Для порта ARM 32-бит, ассемблер теперь поддерживает инструкции
BFC,
BFI,
BFX,
BFXU,
FMULAD,
FMULAF,
FMULSD,
FMULSF,
FNMULAD,
FNMULAF,
FNMULSD,
FNMULSF,
MULAD,
MULAF,
MULSD,
MULSF,
NMULAD,
NMULAF,
NMULD,
NMULF,
NMULSD,
NMULSF,
XTAB,
XTABU,
XTAH,
и
XTAHU.
Для порта ARM 64-бит, ассемблер теперь поддерживает инструкции
VADD,
VADDP,
VADDV,
VAND,
VCMEQ,
VDUP,
VEOR,
VLD1,
VMOV,
VMOVI,
VMOVS,
VORR,
VREV32,
и
VST1.
Для порта PowerPC 64-бит, ассемблер теперь поддерживает инструкции POWER9
ADDEX,
CMPEQB,
COPY,
DARN,
LDMX,
MADDHD,
MADDHDU,
MADDLD,
MFVSRLD,
MTVSRDD,
MTVSRWS,
PASTECC,
VCMPNEZB,
VCMPNEZBCC,
и
VMSUMUDM.
Для порта S390X, ассемблер теперь поддерживает инструкции
TMHH,
TMHL,
TMLH,
и
TMLL.
Для порта X86 64-бит, ассемблер теперь поддерживает 359 новых инструкций,
включая полные наборы расширений AVX, AVX2, BMI, BMI2, F16C, FMA3, SSE2, SSE3, SSSE3, SSE4.1 и SSE4.2.
Ассемблер также больше не реализует MOVL $0, AX
как инструкцию XORL,
чтобы избежать неожиданного сброса флагов состояния.
Gccgo
Из-за согласования полуторгового графика выпуска Go с годовым графиком выпуска GCC, в выпуске GCC 7 содержится версия gccgo Go 1.8.3. Ожидается, что следующий выпуск, GCC 8, будет содержать версию gccgo Go 1.10.
Среда выполнения
Поведение вложенных вызовов
LockOSThread и
UnlockOSThread
изменилось.
Эти функции управляют тем, привязана ли горутина к определённому потоку операционной системы,
так что горутина выполняется только на этом потоке, и поток выполняет только эту горутину.
Ранее, вызов LockOSThread более одного раза подряд
был эквивалентен однократному вызову, и один вызов UnlockOSThread
всегда разблокировал поток.
Теперь вызовы вкладываются: если LockOSThread вызывается несколько раз,
UnlockOSThread должен быть вызван такое же количество раз,
чтобы разблокировать поток.
Существующий код, который был осторожен и не вкладывал эти вызовы, останется корректным.
Существующий код, который неправильно предполагал, что вызовы вкладываются, станет корректным.
Большинство использований этих функций в общедоступном исходном коде Go относятся ко второму случаю.
Поскольку одним из общих случаев использования LockOSThread и UnlockOSThread является возможность надежно изменять состояние, зависящее от потока (например, пространства имен Linux или Plan 9), среда выполнения теперь рассматривает заблокированные потоки как непригодные для повторного использования или для создания новых потоков.
Трассировки стека больше не включают неявные обёртки функций (ранее они были помечены как <autogenerated>), если только сбой или паника не происходит непосредственно в самой обёртке.
В результате, количество пропусков, передаваемых функциям, таким как Caller,
теперь всегда должно соответствовать структуре написанного кода, а не зависеть от решений оптимизации и деталей реализации.
Сборщик мусора был изменён с целью уменьшить его влияние на задержку при выделении памяти. Он теперь использует меньшую долю общего CPU при работе, но может запускаться чаще. Общее количество CPU, потребляемого сборщиком мусора, не изменилось значительно.
Функция GOROOT
теперь по умолчанию (если переменная окружения $GOROOT не установлена)
использует значение GOROOT или GOROOT_FINAL, действующее
в момент компиляции вызывающей программы.
Ранее использовалось значение GOROOT или GOROOT_FINAL, действующее
в момент компиляции инструментария, который компилировал вызывающую программу.
Больше нет ограничения на значение настройки GOMAXPROCS.
(В Go 1.9 это ограничение составляло 1024.)
Производительность
Как и всегда, изменения настолько общие и разнообразные, что точные утверждения о производительности сделать трудно. Большинство программ должны работать немного быстрее благодаря ускорению сборщика мусора, лучшему генерируемому коду и оптимизациям в основной библиотеке.
Сборщик мусора
Многие приложения должны испытывать значительно меньшую задержку при выделении памяти и общую нагрузку на производительность при активном сборщике мусора.
Стандартная библиотека
Все изменения в стандартной библиотеке являются незначительными. Самые вероятные изменения касаются пакетов bytes и net/url, которые могут потребовать обновления существующих программ.
Незначительные изменения в библиотеке
Как всегда, в библиотеке были внесены различные незначительные изменения и обновления, сделанные с учётом обещания совместимости Go 1 promise of compatibility.
archive/tar
В целом, обработка специальных форматов заголовков значительно улучшена и расширена.
FileInfoHeader всегда
записывала UID и GID из её аргумента типа os.FileInfo
(конкретно, из системно-зависимой информации, возвращаемой методом Sys типа FileInfo)
в возвращаемый Header.
Теперь она также записывает имена пользователя и группы, соответствующие этим ID,
а также старшие и младшие номера устройств для файлов устройств.
Новое поле Header.Format типа Format
управляет тем, какой формат заголовка tar использует Writer.
По умолчанию, как и раньше, выбирается наиболее широко поддерживаемый тип заголовка,
способный закодировать необходимые поля заголовка (USTAR, если возможно, иначе PAX, если возможно, иначе GNU).
Reader устанавливает Header.Format для каждого прочитанного заголовка.
Reader и Writer теперь поддерживают произвольные записи PAX,
используя новое поле Header.PAXRecords,
обобщение существующего поля Xattrs.
Reader больше не требует, чтобы имя файла или имя ссылки в заголовках GNU
были корректными UTF-8.
При записи заголовков в формате PAX или GNU, Writer теперь включает
поля Header.AccessTime и Header.ChangeTime (если они установлены).
При записи заголовков в формате PAX, времена включают точность до долей секунды.
archive/zip
Go 1.10 добавляет более полную поддержку времени и кодировок наборов символов в ZIP-архивах.
Оригинальный формат ZIP использовал стандартную кодировку MS-DOS для представления года, месяца, дня, часа, минуты и секунды в полях двух 16-битных значений.
Эта кодировка не может представлять временные зоны или нестандартные секунды, поэтому были введены различные расширения,
позволяющие использовать более богатые кодировки.
В Go 1.10 Reader и Writer
теперь поддерживают широко понимаемое расширение Info-Zip, которое кодирует время отдельно в 32-битном формате Unix «секунды с эпохи».
Новое поле Modified типа time.Time в FileHeader
устарело по сравнению с полями ModifiedTime и ModifiedDate, которые продолжают хранить кодировку MS-DOS.
Reader и Writer теперь принимают общепринятую конвенцию:
если ZIP-архив хранит независимое от временной зоны Unix-время,
он также сохраняет локальное время в поле MS-DOS,
чтобы можно было вывести смещение временной зоны.
Для совместимости методы ModTime и
SetModTime
ведут себя так же, как и в предыдущих версиях; новый код должен напрямую использовать поле Modified.
Заголовок каждого файла в ZIP-архиве имеет бит флага, указывающий,
кодируются ли поля имени и комментария в UTF-8, в отличие от системно-специфичной кодировки по умолчанию.
В Go 1.8 и более ранних версиях Writer никогда не устанавливал бит UTF-8.
В Go 1.9 Writer начал устанавливать бит UTF-8 почти всегда.
Это привело к нарушению создания ZIP-архивов с именами файлов в кодировке Shift-JIS.
В Go 1.10 Writer теперь устанавливает бит UTF-8 только тогда,
когда и имя файла, и поле комментария являются корректными UTF-8 и хотя бы одно из них не является ASCII.
Поскольку не-ASCII кодировки редко выглядят как корректная UTF-8,
новый эвристический подход должен быть корректным почти всегда.
Установка поля NonUTF8 в FileHeader в значение true
полностью отключает эвристику для этого файла.
Также Writer теперь поддерживает установку поля комментария записи конца центрального каталога с помощью вызова новой методы SetComment у Writer.
bufio
Новые методы Reader.Size
и Writer.Size
сообщают о размере базового буфера Reader или Writer.
bytes
Функции
Fields,
FieldsFunc,
Split,
и
SplitAfter
всегда возвращали подсрезы своих входных данных.
В Go 1.10 каждый возвращаемый подсрез теперь имеет ёмкость, равную своей длине,
чтобы при добавлении элементов в один из них не происходило перезаписи смежных данных в оригинальном входе.
crypto/cipher
NewOFB теперь вызывает панику, если передан вектор инициализации неверной длины, как и все остальные конструкторы в этом пакете всегда делали.
(Ранее он возвращал nil-реализацию Stream.)
crypto/tls
Сервер TLS теперь объявляет поддержку подписей SHA-512 при использовании TLS 1.2. Сервер уже поддерживал такие подписи, но некоторые клиенты не выбирали их, если не было явного объявления.
crypto/x509
Certificate.Verify
теперь применяет ограничения имён ко всем именам, содержащимся в сертификате, а не только к тому имени, о котором запросил клиент.
Ограничения расширенного использования ключа также теперь проверяются одновременно.
В результате, после проверки сертификата его можно доверять полностью.
Больше не требуется повторно проверять сертификат для каждого дополнительного имени или использования ключа.
Разобранные сертификаты теперь также сообщают о URI-именах и ограничениях IP, электронной почты и URI, используя новые поля
Certificate
URIs, PermittedIPRanges, ExcludedIPRanges,
PermittedEmailAddresses, ExcludedEmailAddresses,
PermittedURIDomains и ExcludedURIDomains. Сертификаты с
некорректными значениями этих полей теперь отвергаются.
Новые функции MarshalPKCS1PublicKey
и ParsePKCS1PublicKey
преобразуют открытый ключ RSA в и из формата PKCS#1.
Новая функция MarshalPKCS8PrivateKey
преобразует закрытый ключ в формат PKCS#8.
(ParsePKCS8PrivateKey
существовала с момента Go 1.)
crypto/x509/pkix
Name теперь реализует метод
String, который форматирует distinguished name в формате RFC 2253.
database/sql/driver
Драйверы, которые в настоящее время сохраняют буфер назначения, предоставленный
driver.Rows.Next, должны убедиться, что больше не записывают в буфер, назначенный массиву назначения вне этого вызова.
Драйверы должны быть осторожны, чтобы базовые буферы не изменялись при закрытии
driver.Rows.
Драйверы, которые хотят создать sql.DB для своих клиентов, теперь могут реализовать интерфейс
Connector и вызвать новую функцию
sql.OpenDB,
вместо необходимости кодировать всю конфигурацию в строку, передаваемую в
sql.Open.
Драйверы, которые хотят разбирать строку конфигурации только один раз на sql.DB
вместо одного раза на sql.Conn,
или которые хотят получить доступ к контексту каждого sql.Conn,
могут сделать свои реализации Driver
также реализующими новый метод OpenConnector интерфейса
DriverContext.
Драйверы, которые реализуют ExecerContext,
больше не нуждаются в реализации Execer;
аналогично, драйверы, которые реализуют QueryerContext,
больше не нуждаются в реализации Queryer.
Ранее, даже если были реализованы контекстно-зависимые интерфейсы, они игнорировались,
если не были также реализованы не-контекстные интерфейсы.
Чтобы позволить драйверам лучше изолировать различных клиентов, использующих кэшированное соединение драйвера последовательно,
если Conn реализует новый интерфейс
SessionResetter,
database/sql теперь вызовет ResetSession перед
повторным использованием Conn для нового клиента.
debug/elf
В этом выпуске добавлено 348 новых констант пересылки, разделённых между типами пересылки
R_386,
R_AARCH64,
R_ARM,
R_PPC64,
и
R_X86_64.
debug/macho
В Go 1.10 добавлена поддержка чтения переопределений (relocations) из секций Mach-O, с использованием нового поля Relocs структуры Section и новых типов Reloc, RelocTypeARM, RelocTypeARM64, RelocTypeGeneric и RelocTypeX86_64 вместе с соответствующими константами.
Go 1.10 также добавляет поддержку команды загрузки LC_RPATH, представленной типами RpathCmd и Rpath, а также новые именованные константы для различных битовых флагов, найденных в заголовках.
encoding/asn1
Marshal теперь корректно кодирует строки, содержащие звёздочки, как тип UTF8String вместо PrintableString, если только строка не находится в поле структуры с тегом, который принудительно использует PrintableString. Marshal также теперь учитывает теги структур, содержащие директивы application.
Новая функция MarshalWithParams кодирует свой аргумент так, как если бы дополнительные параметры были его тегом поля структуры.
Unmarshal теперь учитывает теги полей структур, использующие директивы explicit и tag.
И Marshal, и Unmarshal теперь поддерживают новый тег поля структуры numeric, обозначающий ASN.1 NumericString.
encoding/csv
Reader теперь запрещает использование бессмысленных значений Comma и Comment, таких как NUL, возврат каретки, символ новой строки, недопустимые руны и символ замены Unicode, а также установку Comma и Comment равными друг другу.
В случае синтаксической ошибки в CSV-записи, которая охватывает несколько строк ввода, Reader теперь сообщает номер строки, с которой началась запись, в новом поле StartLine структуры ParseError.
encoding/hex
Новые функции NewEncoder и NewDecoder обеспечивают потоковое преобразование в шестнадцатеричный формат и обратно, аналогично уже существующим функциям в encoding/base32 и encoding/base64.
Когда функции
Decode
и
DecodeString
встречают некорректный ввод,
они теперь возвращают количество уже преобразованных байт
вместе с ошибкой.
Ранее они всегда возвращали счётчик 0 при возникновении любой ошибки.
encoding/json
Decoder
добавляет новый метод
DisallowUnknownFields,
который заставляет его сообщать об ошибках декодирования при наличии неизвестных полей JSON.
(Поведение по умолчанию всегда заключалось в игнорировании неизвестных полей.)
В результате исправления ошибки в reflect,
Unmarshal
больше не может декодировать в поля внутри
встроенных указателей на неэкспортируемые типы структур,
поскольку он не может инициализировать неэкспортируемый встроенный указатель
для указания на новое хранилище.
Unmarshal теперь возвращает ошибку в этом случае.
encoding/pem
Encode
и
EncodeToMemory
больше не генерируют частичный вывод при получении блока,
который невозможно закодировать как данные PEM.
encoding/xml
Новая функция
NewTokenDecoder
аналогична
NewDecoder,
но создаёт декодер, читающий из TokenReader
вместо потока байтов в формате XML.
Это предназначено для возможности создания трансформеров потоков XML в клиентских библиотеках.
flag
Функция
Usage по умолчанию теперь выводит
первую строку своего результата в
CommandLine.Output()
вместо того, чтобы предполагать os.Stderr,
чтобы сообщение об использовании корректно перенаправлялось для
клиентов, использующих CommandLine.SetOutput.
PrintDefaults теперь
добавляет соответствующую отступы после перевода строки в строках использования флагов,
чтобы многострочные строки использования отображались корректно.
FlagSet добавляет новые методы
ErrorHandling,
Name
и
Output,
для получения настроек, переданных в
NewFlagSet
и
FlagSet.SetOutput.
go/doc
Чтобы поддержать описанное выше изменение в документации, функции, возвращающие срезы типа T, *T, **T и так далее, теперь отображаются в списке Funcs структуры Type, а не в списке Funcs пакета Package.
go/importer
Функция For теперь принимает непустой аргумент lookup.
go/printer
Изменения в форматировании исходного кода Go, описанные в разделе gofmt выше, реализованы в пакете go/printer и также влияют на вывод пакета более высокого уровня go/format.
hash
Реализации интерфейса Hash теперь рекомендуются к реализации интерфейсов encoding.BinaryMarshaler и encoding.BinaryUnmarshaler, чтобы позволить сохранять и восстанавливать внутреннее состояние, и все реализации в стандартной библиотеке (hash/crc32, crypto/sha256 и так далее) теперь реализуют эти интерфейсы.
html/template
Новый тип контента Srcset позволяет корректно обрабатывать значения внутри атрибута srcset тегов img.
math/big
Int теперь поддерживает преобразования в и из оснований 2 через 62 в методах SetString и Text. (Ранее поддерживались только основания 2 через 36.) Значение константы MaxBase было обновлено.
Int добавляет новый метод CmpAbs, который аналогичен методу Cmp, но сравнивает только абсолютные значения (не знаки) своих аргументов.
Float добавляет новый метод Sqrt для вычисления квадратных корней.
math/cmplx
Разрезы ветвей и другие граничные случаи в функциях Asin, Asinh, Atan и Sqrt были исправлены для соответствия определениям, используемым в стандарте C99.
math/rand
Новая функция Shuffle и соответствующий метод
Rand.Shuffle перемешивают входную последовательность.
math
Новые функции
Round
и
RoundToEven
округляют свои аргументы до ближайшего целого числа с плавающей точкой;
Round округляет полуцелое число до его большего целого соседа (от нуля),
в то время как RoundToEven округляет полуцелое число до его четного целого соседа.
Новые функции
Erfinv
и
Erfcinv
вычисляют обратную функцию ошибок и
обратную дополнительную функцию ошибок.
mime/multipart
Reader
теперь принимает части с пустыми атрибутами имени файла.
mime
ParseMediaType теперь отбрасывает
недопустимые значения атрибутов; ранее возвращались эти значения как пустые строки.
net
Реализации Conn и
Listener
в этом пакете теперь гарантируют, что когда Close возвращает управление,
базовый дескриптор файла был закрыт.
(В более ранних версиях, если Close останавливал ожидающие операции ввода-вывода
в других горутинах, закрытие дескриптора могло произойти в одной из этих
горутин непосредственно после возврата из Close.)
TCPListener и
UnixListener
теперь реализуют
syscall.Conn,
чтобы позволить установку параметров на базовом дескрипторе файла
с использованием syscall.RawConn.Control.
Реализации Conn, возвращаемые Pipe,
теперь поддерживают установку тайм-аутов чтения и записи.
Методы IPConn.ReadMsgIP,
IPConn.WriteMsgIP,
UDPConn.ReadMsgUDP,
и
UDPConn.WriteMsgUDP,
теперь реализованы на Windows.
net/http
На стороне клиента HTTP-прокси (наиболее часто настраивается с помощью
ProxyFromEnvironment)
может теперь указываться как URL с протоколом https://,
что означает, что клиент подключается к прокси через HTTPS перед выполнением стандартного, проксированного HTTP-запроса.
(Ранее HTTP-прокси URLs должны были начинаться с http:// или socks5://.)
На стороне сервера, FileServer и его однофайловый аналог ServeFile
теперь применяют проверку If-Range к запросам HEAD.
FileServer также теперь сообщает об ошибках чтения каталогов в Server’s ErrorLog.
Обработчики, предоставляющие содержимое, теперь также опускают заголовок Content-Type при предоставлении содержимого нулевой длины.
Метод WriteHeader у ResponseWriter теперь вызывает панику,
если передан недопустимый (не трёхзначный) код состояния.
Server больше не будет добавлять неявный заголовок Content-Type, если Handler не записывает никаких данных.
Redirect теперь устанавливает заголовок Content-Type перед записью HTTP-ответа.
net/mail
ParseAddress и
ParseAddressList
теперь поддерживают различные устаревшие форматы адресов.
net/smtp
Client добавляет новый
Noop метод,
для проверки, отвечает ли сервер.
Он также теперь защищается от возможного SMTP-инъекции во входные данные
методов Hello
и Verify.
net/textproto
ReadMIMEHeader
теперь отклоняет любой заголовок, начинающийся с строки продолжения (отступа).
Ранее заголовок с отступом в первой строке обрабатывался так, как если бы первая строка не имела отступа.
net/url
ResolveReference
теперь сохраняет несколько начальных слешей в целевом URL.
Ранее несколько начальных слешей перезаписывались в один слеш,
что приводило к неправильной работе http.Client
при определённых перенаправлениях.
Например, вывод следующего кода изменился:
<code>base, _ := url.Parse("http://host//path//to/page1")
target, _ := url.Parse("page2")
fmt.Println(base.ResolveReference(target))
</code>
Обратите внимание на двойные слеши вокруг path.
В Go 1.9 и более ранних версиях разрешённый URL был http://host/path//to/page2:
двойной слеш перед path неправильно перезаписывался в один слеш, тогда как двойной слеш после path
сохранялся правильно.
Go 1.10 сохраняет оба двойных слеша, разрешая http://host//path//to/page2
в соответствии с RFC 3986.
Это изменение может нарушить работу существующих программ с ошибками, которые непреднамеренно создают базовый URL с двойным слэшем в начале пути и непреднамеренно полагаются на ResolveReference для исправления этой ошибки. Например, это может произойти, если код добавляет префикс хоста, такой как http://host/, к пути вида /my/api, в результате чего получается URL с двойным слэшем: http://host//my/api.
Методы UserInfo теперь обрабатывают nil-получатель как эквивалентный указателю на нулевой UserInfo. Ранее они вызывали панику.
os
File добавляет новые методы
SetDeadline,
SetReadDeadline,
и
SetWriteDeadline,
которые позволяют устанавливать дедлайны ввода-вывода, когда базовый дескриптор файла поддерживает неблокирующие операции. Определения этих методов соответствуют тем, что в net.Conn.
Если метод ввода-вывода завершается ошибкой из-за отсутствия дедлайна, он возвращает ошибку таймаута; новая функция IsTimeout сообщает, представляет ли ошибка таймаут.
Аналогично net.Conn,
метод Close типа File
теперь гарантирует, что когда Close возвращает управление,
базовый дескриптор файла закрыт.
(В более ранних версиях,
если Close останавливал ожидающие операции ввода-вывода
в других горутинах, закрытие дескриптора могло произойти в одной из этих
горутин через некоторое время после возврата из Close.)
В системах BSD, macOS и Solaris,
Chtimes
теперь поддерживает установку времени файла с наносекундной точностью
(при условии, что базовая файловая система может представлять такие значения).
reflect
Функция Copy теперь позволяет копировать
из строки в байтовый массив или байтовый срез, чтобы соответствовать
встроенной функции copy.
В структурах, встроенные указатели на неэкспортируемые типы структур ранее неправильно отображались с пустым PkgPath
в соответствующем StructField,
в результате чего для таких полей
Value.CanSet
неправильно возвращало true,
а Value.Set
неправильно выполнялась.
Метаданные были исправлены;
для таких полей
CanSet теперь корректно возвращает false,
а Set теперь корректно вызывает панику.
Это может повлиять на отражение-основанные десериализаторы,
которые ранее могли десериализовать в такие поля,
но теперь не могут.
Например, см. encoding/json notes.
runtime/pprof
Как упоминалось выше, профили блокировок и мьютексов теперь включают информацию о символах, благодаря чему их можно просматривать без необходимости иметь бинарный файл, сгенерировавший эти профили.
strconv
ParseUint теперь возвращает целое число максимальной величины соответствующего размера вместе с ошибкой ErrRange, как уже было описано в документации. Ранее функция возвращала 0 при возникновении ошибок ErrRange.
strings
Новый тип
Builder служит заменой
bytes.Buffer для случая использования, когда текст накапливается в string результат. API типа Builder представляет собой ограниченное подмножество API bytes.Buffer, которое позволяет безопасно избежать дублирования данных во время вызова метода String.
syscall
В Windows,
новое поле SysProcAttr Token,
типа Token, позволяет создавать процесс, который выполняется от имени другого пользователя во время StartProcess
(а значит и во время os.StartProcess и
exec.Cmd.Start).
Новая функция CreateProcessAsUser
обеспечивает доступ к базовому системному вызову.
В системах BSD, macOS и Solaris реализован UtimesNano.
time
LoadLocation теперь использует каталог
или разархивированный zip-файл, указанный переменной окружения $ZONEINFO,
до того как будет осуществлен поиск в стандартном списке известных путей установки или в $GOROOT/lib/time/zoneinfo.zip.
Новая функция LoadLocationFromTZData
позволяет преобразовать данные файла часового пояса IANA в Location.
unicode
Пакет unicode и связанная с ним поддержка по всей системе были обновлены с Unicode 9.0 до
Unicode 10.0,
что добавляет 8 518 новых символов, включая четыре новых письменности, одно новое свойство,
символ валюты Bitcoin и 56 новых эмодзи.