Примечания к выпуску Go 1.3
Введение в Go 1.3
Последний выпуск Go, версия 1.3, появился через шесть месяцев после 1.2, и не содержит изменений в языке. Он сосредоточен в основном на работе по реализации, обеспечивая точную сборку мусора, значительную рефакторинг компилятора, что приводит к более быстрой компиляции, особенно для больших проектов, существенные улучшения производительности по всем направлениям, и поддержку DragonFly BSD, Solaris, Plan 9 и архитектуры Google Native Client (NaCl). Также имеется важное уточнение модели памяти в части синхронизации. Как и всегда, Go 1.3 выполняет обещание совместимости, и почти всё будет продолжать компилироваться и запускаться без изменений при переходе к 1.3.
Изменения в поддерживаемых операционных системах и архитектурах
Удаление поддержки Windows 2000
Microsoft прекратила поддержку Windows 2000 в 2010 году. Поскольку у нее есть проблемы с реализацией в части обработки исключений (сигналов в терминах Unix), с версии Go 1.3 она также не поддерживается Go.
Поддержка DragonFly BSD
Go 1.3 теперь включает экспериментальную поддержку DragonFly BSD на архитектурах amd64 (64-битный x86) и 386 (32-битный x86).
Используется DragonFly BSD 3.6 или выше.
Поддержка FreeBSD
Это не было объявлено в то время, но с момента выпуска Go 1.2 поддержка Go на FreeBSD требует FreeBSD 8 или выше.
Начиная с Go 1.3, поддержка Go на FreeBSD требует, чтобы ядро было скомпилировано с флагом
COMPAT_FREEBSD32.
В связи со сменой на EABI syscalls для ARM-платформ, Go 1.3 будет работать только на FreeBSD 10. Платформы x86, 386 и amd64, остаются неизменными.
Поддержка Native Client
Поддержка виртуальной машины Native Client вернулась в Go с выпуском 1.3.
Она работает на 32-битных архитектурах Intel (GOARCH=386) и также на 64-битных Intel, но используя
32-битные указатели (GOARCH=amd64p32).
Пока не предусмотрена поддержка Native Client на ARM.
Обратите внимание, что это Native Client (NaCl), а не Portable Native Client (PNaCl).
Детали о Native Client можно найти здесь;
как настроить версию Go описано здесь.
Поддержка NetBSD
Начиная с Go 1.3, поддержка Go на NetBSD требует NetBSD 6.0 или выше.
Поддержка OpenBSD
Начиная с Go 1.3, поддержка Go на OpenBSD требует OpenBSD 5.5 или выше.
Поддержка Plan 9
Go 1.3 теперь включает экспериментальную поддержку Plan 9 на архитектуре 386 (32-битный x86).
Требуется syscall Tsemacquire, который был добавлен в Plan 9 с июня 2012 года.
Поддержка Solaris
Go 1.3 теперь включает экспериментальную поддержку Solaris на архитектуре amd64 (64-битный x86).
Требуется illumos, Solaris 11 или выше.
Изменения в модели памяти
Модель памяти Go 1.3 добавляет новое правило относящееся к отправке и получению данных по буферизованным каналам, чтобы сделать явным, что буферизованный канал может использоваться как простой семафор, используя отправку в канал для захвата и получение из канала для освобождения. Это не изменение языка, а просто уточнение о предполагаемом свойстве обмена данными.
Изменения в реализации и инструментах
Стек
Go 1.3 изменила реализацию стеков горутин с предыдущей, «сегментированной» модели на непрерывную модель. Когда горутине требуется больше стека, чем доступно, её стек передаётся в более крупный блок памяти. Накладные расходы этой операции хорошо амортизируются и устраняют старую проблему «горячей точки», когда вычисление многократно пересекает границу сегмента. Детали, включая числа производительности, находятся в этом документе проектирования.
Изменения в сборщике мусора
Некоторое время назад сборщик мусора стал точным при анализе значений в куче; в релизе Go 1.3 добавлена эквивалентная точность для значений на стеке. Это означает, что непоказательное значение Go, например целое число, никогда не будет ошибочно воспринято как указатель и не помешает освобождению неиспользуемой памяти.
Начиная с Go 1.3, среда выполнения предполагает, что значения с типом указателя содержат указатели, а другие значения — нет. Это предположение лежит в основе точного поведения как расширения стека, так и сборки мусора. Программы, использующие пакет unsafe для хранения целых чисел в значениях с типом указателя, являются недопустимыми и будут аварийно завершаться, если среда выполнения обнаружит такое поведение. Программы, использующие пакет unsafe для хранения указателей в значениях с целочисленным типом, также являются недопустимыми, но более трудно диагностируются во время выполнения. Поскольку указатели скрыты от среды выполнения, расширение стека или сборка мусора могут освободить память, на которую они указывают, создавая висячие указатели.
Обновление: Код, который использует unsafe.Pointer для преобразования целочисленного значения, хранящегося в памяти, в указатель, является недопустимым и должен быть переписан.
Такой код может быть выявлен с помощью go vet.
Итерация по картам
Итерации по небольшим картам больше не происходят в определенном порядке. Go 1 определяет, что «Порядок итерации по картам не определён и не гарантируется одинаковым от одной итерации к другой.» Чтобы предотвратить зависимость кода от порядка итерации по картам, Go 1.0 начал каждую итерацию карты с случайного индекса в карте. Новая реализация карт, представленная в Go 1.1, забыла случайным образом изменять порядок итерации для карт с восемью или менее элементами, хотя порядок итерации может по-прежнему отличаться от системы к системе. Это позволило людям писать программы на Go 1.1 и Go 1.2, которые зависят от порядка итерации по небольшим картам, и поэтому работают надежно только на определённых системах. Go 1.3 снова вводит случайный порядок итерации для небольших карт, чтобы выявить эти ошибки.
Обновление: Если код предполагает фиксированный порядок итерации для небольших карт, он будет сломан и должен быть переписан так, чтобы не делать таких предположений. Поскольку затрагиваются только небольшие карты, проблема чаще всего возникает в тестах.
Линкер
В рамках обобщённой рефакторинг линкера Go, компиляторы и линкеры были переработаны.
Линкер по-прежнему является C-программой, но теперь фаза выбора инструкций, которая была частью линкера, была перемещена в компилятор через создание новой
библиотеки под названием liblink.
Выполняя выбор инструкций только один раз при первом компилировании пакета,
это может значительно ускорить компиляцию больших проектов.
Обновление: Хотя это существенное внутреннее изменение, оно не должно влиять на программы.
Статус gccgo
Релиз GCC 4.9 будет содержать версию gccgo Go 1.2 (не 1.3). Графики релизов проектов GCC и Go не совпадают, что означает, что 1.3 будет доступна в ветке разработки, но следующий релиз GCC, 4.10, скорее всего будет содержать версию gccgo Go 1.4.
Изменения в команде go
Команда cmd/go имеет несколько новых
возможностей.
Подкоманды go run и
go test поддерживают новый параметр -exec для указания альтернативного способа запуска результирующего двоичного файла.
Её прямое назначение — поддержка NaCl.
Поддержка покрытия тестов подкоманды go test
теперь автоматически устанавливает режим покрытия в -atomic,
когда включён детектор гонок, чтобы исключить ложные отчёты о нестандартном
доступе к счётчикам покрытия.
Подкоманда go test теперь всегда собирает пакет, даже если в нём отсутствуют тестовые файлы. Ранее, если тестовые файлы отсутствовали, подкоманда ничего не делала.
Подкоманда go build поддерживает новый флаг -i, который позволяет установить зависимости указанной цели, но не саму цель.
Перекрёстная компиляция с включённым cgo теперь поддерживается.
Переменные окружения CC_FOR_TARGET и CXX_FOR_TARGET используются при запуске all.bash для указания перекрёстных компиляторов для C и C++ кода соответственно.
Наконец, команда go теперь поддерживает пакеты, импортирующие Objective-C файлы (с расширением .m) через cgo.
Изменения в cgo
Команда cmd/cgo, которая обрабатывает объявления import "C" в пакетах Go,
исправила серьёзную ошибку, которая могла привести к остановке компиляции некоторых пакетов.
Ранее, все указатели на неполные структуры в Go переводились в тип *[0]byte,
что мешало компилятору Go диагностировать передачу одного вида указателя на структуру в функцию, ожидающую другой.
Go 1.3 исправляет эту ошибку, переводя каждую различную неполную структуру в отдельный именованный тип.
Для C-объявления typedef struct S T для неполной структуры struct S,
некоторый Go-код использовал эту ошибку для неявного использования типов C.struct_S и C.T взаимозаменяемо.
Теперь cgo явно разрешает такое использование, даже для завершённых структур.
Однако, некоторые Go-программы также использовали эту ошибку для передачи (например) *C.FILE
из одного пакета в другой.
Это теперь недопустимо и больше не работает: в общем случае пакеты Go должны избегать экспозиции C-типов и имён в своих API.
Обновление: Код, который путает указатели на неполные типы или передаёт их через границы пакетов, больше не будет компилироваться и должен быть переписан.
Если конверсия корректна и должна быть сохранена,
используйте явное преобразование через unsafe.Pointer.
SWIG 3.0 требуется для программ, использующих SWIG
Для Go-программ, использующих SWIG, теперь требуется SWIG версии 3.0.
Команда cmd/go теперь напрямую связывает сгенерированные SWIG файлы объектов в исполняемый файл, вместо того чтобы собирать и связывать с общими библиотеками.
Разбор флагов командной строки
В инструментарии gc, ассемблеры теперь используют те же правила разбора флагов командной строки, что и пакет flag в Go, что отличается от традиционного Unix-стиля разбора флагов.
Это может повлиять на скрипты, которые вызывают инструмент напрямую.
Например,
go tool 6a -SDfoo теперь нужно писать как
go tool 6a -S -D foo.
(То же изменение было внесено в компиляторы и линковщики в Go 1.1.)
Изменения в godoc
При запуске с флагом -analysis,
godoc
теперь выполняет сложный статический анализ кода, который он индексирует.
Результаты анализа отображаются как в представлении исходного кода, так и в представлении документации пакета, и включают граф вызовов каждого пакета,
а также связи между
определениями и ссылками,
типами и их методами,
интерфейсами и их реализациями,
операциями отправки и получения на каналах,
функциями и их вызывающими,
а также точки вызова и их вызываемые функции.
Разное
Программа misc/benchcmp, которая сравнивает производительность между запусками бенчмарков, была переписана.
Ранее она была обёрткой на shell и awk в основном репозитории, теперь она — Go-программа в репозитории go.tools.
Документация доступна здесь.
Для тех немногих, кто собирает дистрибутивы Go, инструмент misc/dist был перемещён и переименован;
он теперь находится в misc/makerelease, всё ещё в основном репозитории.
Производительность
Производительность исполняемых файлов Go в данном релизе улучшена во многих случаях благодаря изменениям в среде выполнения и сборке мусора, а также некоторым изменениям в библиотеках. Значительные улучшения включают:
- Среда выполнения теперь обрабатывает defer более эффективно, снижая объем используемой памяти примерно на две килобайта на горутину, вызывающую defer.
- Сборщик мусора ускорен, используя конкурентный алгоритм очистки, лучшую параллелизацию и большие страницы. Кумулятивный эффект может составлять снижение времени пауз сборщика на 50–70%.
- Детектор гонок (см. это руководство) теперь работает примерно на 40% быстрее.
- Пакет регулярных выражений
regexpтеперь значительно быстрее для определённых простых выражений благодаря реализации второго одно-проходного движка выполнения. Выбор движка происходит автоматически; подробности скрыты от пользователя.
Кроме того, среда выполнения теперь включает в дампы стеков информацию о том, как долго горутина была заблокирована, что может быть полезно при отладке взаимоблокировок или проблем с производительностью.
Изменения в стандартной библиотеке
Новые пакеты
В стандартную библиотеку был добавлен новый пакет debug/plan9obj.
Он реализует доступ к объектным файлам Plan 9 a.out.
Значительные изменения в библиотеке
Ранее в crypto/tls существовала ошибка,
которая позволяла случайно пропустить проверку TLS.
В Go 1.3 эта ошибка исправлена: необходимо указать либо ServerName, либо
InsecureSkipVerify, и если указан ServerName, он применяется строго.
Это может привести к поломке существующего кода, который неправильно полагался на предыдущее поведение.
В net/http пакете теперь реализован
новый метод Request.ParseMultipartForm,
который теперь возвращает ошибку, если заголовок Content-Type тела запроса
не является multipart/form-data.
До Go 1.3 он молчаливо завершался и возвращал nil.
Код, зависящий от предыдущего поведения, должен быть обновлён.
net пакете структура Dialer теперь
имеет поле KeepAlive, позволяющее задать период keep-alive для соединения.net/http пакет теперь
предоставляет необязательный обратный вызов Server.ConnState
для перехвата различных фаз жизненного цикла соединения сервера
(см. ConnState).
Это может быть использовано для реализации ограничения скорости или грациозного завершения.net/http пакет теперь
имеет необязательное поле Client.Timeout
для указания общего времени ожидания запросов, выполненных с использованием клиента.net/http пакет теперь
закрывает Request.Body
последовательно, даже в случае ошибки.os/exec теперь реализует
то, что документация всегда говорила о относительных путях для исполняемых файлов.
В частности, он вызывает LookPath
только в том случае, если имя файла бинарного файла не содержит разделителей путей.SetMapIndex
в пакете reflect
больше не вызывает панику при удалении из nil карты.runtime.Goexit
и все остальные горутины завершают выполнение, программа теперь всегда завершается аварийно,
сообщая о выявленной взаимоблокировке.
Ранее версии Go обрабатывали эту ситуацию несогласованно: большинство случаев
сообщалось как взаимоблокировки, но некоторые тривиальные случаи завершались чисто.runtime/debug теперь имеет новую функцию
debug.WriteHeapDump,
которая записывает описание кучи.CanBackquote
в пакете strconv
теперь рассматривает символ DEL, U+007F, как
непечатаемый.syscall теперь предоставляет
SendmsgN
как альтернативную версию
Sendmsg,
возвращающую количество записанных байт.syscall теперь
поддерживает соглашение о вызове cdecl через добавление новой функции
NewCallbackCDecl
в дополнение к существующей функции
NewCallback.testing теперь
диагностирует тесты, вызывающие panic(nil), что почти всегда является ошибкой.
Также тесты теперь записывают профили (если вызваны с флагами профилирования) даже при неудачном завершении.unicode и связанная с ним поддержка
во всей системе были обновлены с Unicode 6.2.0 до Unicode 6.3.0.