Примечания к выпуску 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 в данном релизе улучшена во многих случаях благодаря изменениям в среде выполнения и сборке мусора, а также некоторым изменениям в библиотеках. Значительные улучшения включают:

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

Изменения в стандартной библиотеке

Новые пакеты

В стандартную библиотеку был добавлен новый пакет 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, возвращающую количество записанных байт.
  • В Windows пакет syscall теперь поддерживает соглашение о вызове cdecl через добавление новой функции NewCallbackCDecl в дополнение к существующей функции NewCallback.
  • Пакет testing теперь диагностирует тесты, вызывающие panic(nil), что почти всегда является ошибкой. Также тесты теперь записывают профили (если вызваны с флагами профилирования) даже при неудачном завершении.
  • Пакет unicode и связанная с ним поддержка во всей системе были обновлены с Unicode 6.2.0 до Unicode 6.3.0.
  • GoRu.dev Golang на русском

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