...
Run Format

Go 1.3 リリースノート

Go1.3のイントロダクション

Go1.3のリリースは、Go1.2をリリースしてから6ヶ月後を予定しています。 そして、いかなる言語仕様の変更もありません。 Go1.3では、ガーベッジコレクションやコンパイラツールチェーンの改善に集中しています。 特に大規模なプロジェクトにおいて、ビルドが高速になるでしょう。 他にも全体的にパフォーマンスの大幅な改善やサポート環境の追加(DragonFly BSD, Solaris, Plan9)、 GoogleのNative Client architecture(NaCl)のサポートが含まれます。 また同期に関連したメモリモデルの改良もありますが、これも重要です。 当然、後方互換性は保っています。 Go1.3に移行しても、大抵は変更なしでも問題ないはずです。

サポート対象OSに関する変更点

Windows 2000のサポート終了

マイクロソフトは2010年にWindows 2000をサポートを終了しました。 例外機構(Unixにおけるシグナル)の実装が難しいため、 Go1.3でも同様にサポートを終了します。

DragonFly BSDのサポート

Go1.3では、試験的にamd64 (64-bit x86)と386 (32-bit x86) アーキテクチャ上で動作するDragonFly BSDをサポートします。DragonFly BSD 3.6以上が必要です。

Free BSDのサポート

これまで公式にアナウンスしていませんでしたが、Go1.2からFreeBSD 8以上のFreeBSDをサポートします。

Go1.3をFreeBSDで使用するためには、kernelにCOMPAT_FREEBSD32 flagを 設定してコンパイルしなければいけません。

ARMプラットフォーム用EABIのシステムコールへの切り替えと協調して、 Go1.3はFreeBSD 10のみで実行されます。 x86プラットフォーム、386およびamd64は、影響を受けません。

Native Clientのサポート

Go1.3で、Native Clientの仮想マシンアーキテクチャのサポートが復活します。 32ビットインテルアーキテクチャ(GOARCH=386)、 または64ビットでポインタは32ビット(GARCH=amd64p32)のどちらかの環境で動作します。 ARMはまだサポートしていません。Portable Native Client (PNaCl)と混同しないように注意して下さい。 Navite Clinetについての詳細はここを参照してください。 またGoのバージョンを指定する方法についてはここに記載があります。

NetBSDのサポート

Go1.3では、NetBSD 6.0以上でNetBSDをサポートします。

OpenBSDのサポート

Go1.3では、OpenBSD 5.5以上でOpenBSDをサポートします。

Plan 9のサポート

Go1.3では、試験的に386 (32-bit x86) アーキテクチャ上で動作するPlan9をサポートします。 2012-06以降のPlan 9のTsemacquire syscall が必要です。

Solarisのサポート

Go1.3では、試験的にamd64 (64-bit x86) アーキテクチャ上で動作するSolarisをサポートします。 illumos、Solaris 11以上が必要です。

メモリモデルの変更点

Go1.3では、メモリモデルに新しい規約を追加しました。 これはバッファ付きチャネルの送受信に関するもので、それが簡易なセマフォとして使用できることを明示しました。 チャネルへの送信は資源を獲得し、チャネルからの受信は資源を開放します。 言語仕様の変更ではなく、コミュニケーションに期待される性質を明らかにしただけです。

実装とツールの変更点

スタック

Go1.3では、ゴルーチンのスタック実装が以前のセグメント方式からcontiguous方式に変更されています。 実行中のゴルーチンがさらにスタック領域を必要としたとき、スタックはメモリ上のより大きな単一領域に転送されます。 セグメント境界を跨いで計算を繰り返すようなケースでは、転送操作のオーバーヘッドは無視できるし、 さらに”ホットスポット”問題も解消できます。 パフォーマンスの詳細は、design documentを見て下さい。

ガーベッジコレクタの変更点

これまで、ガーベッジコレクタがヒープ領域の値の評価は正確でした。 Go1.3では、スタック上の値も同様に正確に評価されます。 つまり、ポインタでないint型の値がポインタに間違われたり、未使用メモリとして再利用されるようなことはありません。

Go1.3以降では、ランタイムはポインタ型の値はポインタを含み、他の値ではないと仮定します。 この仮定は、スタックの拡大とガーベッジコレクションの両方の正確な振る舞いの基本です。 ポインタ型の値に整数を格納するために、 package unsafe を使用するプログラムは不正であり、ランタイムがこの振る舞いを検出した場合にはクラッシュします。 整数型の値にポインタを格納するために、 package unsafe を使用するプログラムもまた不正ですが、実行時に検出することは困難です。 ポインタはランタイムから隠されているため、スタックの拡大や、ガーベッジコレクションは、ダングリングポインタ(dangling pointer)を作成し、これらが指すメモリを再利用することができます。

更新: ポインタにメモリへ保持する整数型の値を変換するために、 unsafe.Pointer を使用するコードは不正であり、書き直す必要があります。 このようなコードは go vet で識別することができます。

Map iteration

小規模なmapのイテレーションは、もう一貫した順序では動きません。 Go1では “map上のイテレーション順序は指定されず、次のイテレーションで同じになることは保証されない” と定義されています。 mapのイテレーション順序の依存からコードを守るために、Go1.0以降はmapのランダムなインデックスでmapのイテレーションをします。 イテレーションの順序はシステムによって異なりますが、Go1.1で導入された新しいmapの実装では、8個以下のエントリを持つmapのイテレーション順序はランダムではありませんでした。 そのためGo1.1とGo1.2では、小さいmapのイテレーション順序に依存した、特定のシステムでだけ安定して動作するプログラムを書くことができました。 Go1.3では、これらのバグを洗い出すために、小さいmapでもイテレーション順序はランダムになりました。

更新: 小さなmapでイテレーション順序が固定されていることを仮定しているコードは、 そのような仮定をしないように書き直す必要があります。 小さなmapだけが影響を受けるため、この問題はテストで多く発生します。

Goリンカのオーバーホールの一環で、 コンパイラとリンカはリファクタリングされました。 リンカは依然としてCで実装されています。しかし、リンカの一部だった命令選択は、 liblinkと呼ばれる新しいライブラリを実装して、コンパイラで実行されるようになりました。 パッケージの初回コンパイルで命令選択を一度しか行わないので、大規模なプロジェクトのコンパイルは大幅に高速になります。

更新: これは大きな内部変更ですが、プログラムには影響しないはずです。

gccgoのステータス

GCC4.9では、Go1.2(1.3ではなく)をサポートする予定です。GCCとGoのリリース計画は同期していません。 よってGo1.3は開発ブランチで使用可能ですが、おそらく次のGCC4.10ではGo1.4がサポートされる予定です。

Goコマンドの変更点

cmd/goコマンドに新しい機能がいくつか追加されました。 新たに、go rungo testサブコマンドは -execオプションをサポートしました。 これは、ビルドしたバイナリを実行するための別の方法を指定できます。直接の目的は、NaClをサポートすることです。

競合ディテクタが有効になっているとき、go testサブコマンドのカバレッジサポートは 自動的にカバレッジモードに-atomicを指定します。 これは、カバレッジカウンタへの安全でないアクセスが誤って検出されてしまうことを防ぐためです。

go testサブコマンドは、 テストファイルがない場合でもパッケージを全てビルドするようになりました。 以前は、テストファイルがない場合は何もしませんでした。

go buildサブコマンドは、 ターゲット自体ではなく、指定したターゲットの依存をインストールするために新しい-iオプションをサポートします。

cgoでクロスコンパイルがサポートされるようになりました。 all.bashを実行する際、それぞれCとC++のコード用のクロスコンパイラを指定するために CC_FOR_TARGET と CXX_FOR_TARGET の環境変数が使われます。

最後に、goコマンドは、cgoを通じてObjective-Cファイル(ファイル拡張子が.m)をインポートする パッケージをサポートしています。

cgoの変更点

Goのパッケージでimport "C"宣言を処理するcmd/cgoコマンドは、 いくつかのパッケージでコンパイルが停止する深刻なバグが修正されました。 以前は、不完全な構造体型へのポインタはGoの*[0]byte型に変換され、Goコンパイラは構造体へのポインタを違うものを期待している関数へ渡していることを検出できませんでした。 Go 1.3ではこの誤りを修正し、不完全な構造体はそれぞれ違う名前の型へ変換されるようになりました。

Cの宣言としてtypedef struct S Tが不完全な構造体struct Sとともに与えられたとき、 一部のGoのコードはこのバグを、C.struct_SC.Tをお互いに入れ替えるために使っていました。 Cgoはこのような使い方を、完全な構造体型でも明確に許すようになりました。 しかし、一部のGoのコードはこのバグを(たとえば)*C.FILEをあるパッケージから別のパッケージへ渡すために使っています。 これは正しくなく、動作しなくなりました: 一般に、GoのパッケージはCの型と名前をAPI上で公開するべきではありません。

更新: 不完全な型へのポインタを混同しているコードや、パッケージ境界を跨いで渡しているコードはコンパイルできなくなりました。書き直す必要があります。 もしその変換が正しく、かつそのままにしたいのであれば、unsafe.Pointerを使って明示的に変換してください。

SWIGを使用しているプログラムはSWIG 3.0が必要

SWIGを使用しているGoのプログラムは、SWIGバージョン3.0が必要になりました。 cmd/goコマンドはSWIGで生成されたオブジェクトファイルを、共有ライブラリをビルドしてリンクするのではなく、バイナリに直接リンクするようなりました。

コマンドライン引数の解析

Goコマンドツールチェーンで、アセンブラはGo flagパッケージと同じコマンドライン引数解析ルールを使用するようになりました。 これは伝統的なUnixコマンドライン引数解析を元にしています。もしスクリプト内で直接ツールを呼び出している場合には影響を受けるかもしれません。 例えば、go tool 6a -SDfoogo tool 6a -S -D fooと書かなければいけません。 (同様の変更は、Go 1.1のときにリンカとコンパイラにもありました。)

godocの変更

godoc-analysisフラグつきで実行すると、 コードに対して高度な静的解析をするようになりました。 解析結果はソースビューとドキュメントビューのどちらでもみることができ、パッケージごとの関数の呼び出しグラフ、 定義と参照、型とそのメソッド、インタフェースとその実装、チャネルの送信と受信、関数とその呼び出し元、 呼び出す場所と呼び出されるもの同士の関連性が含まれています。

その他

ベンチマーク結果のパフォーマンスを比較するためのツールmisc/benchcmpが書き直されました。 shellとawkで書かれたスクリプトがメインレポジトリに存在しましたが、現在はGoで実装されていてgo.toolsレポジトリに含まれています。 ドキュメントはここにあります。

Goのディストリビューションを構築する人のため、misc/distに存在したツールを移動しました。 これらのツールは、現在はmisc/makereleaseにあります。

パフォーマンス

Go1.3では、ランタイムやガーベッジコレクション、さらに標準ライブラリにもいくつか変更が入っています。 そのため、たくさんのケースで性能が改善されています。 重要な点を上げると、

また、ランタイムはスタックダンプにゴルーチンのブロックされた時間を含むようになりました。 これは、デッドロックやパフォーマンス問題をデバッグするときに役立ちます。

標準ライブラリの変更点

新しいパッケージ

新たにdebug/plan9objパッケージが追加されました。 これは、Plan9のa.outオブジェクトファイル向けの実装です。

大規模な変更点

crypto/tlsに存在していたバグによって、気づかないうちにTLS認証をスキップできてしまいました。 Go1.3で、このバグは修正されています。ServerNameかInsecureSkipVerifyのどちらかは必ず指定しなければいけません。 ServerNameが指定されている場合、ServerNameの使用が強制されます。 これは破壊的変更です。もしこれまでの安全でない振る舞いに依存したコードを書いている場合は、コードの変更が必要です。

標準ライブラリにsync.Poolという重要な型が追加されました。 これを利用することで、自動でメモリが再利用されるようなキャッシュ機構のようなものを簡単に実装できます。

testingパッケージのベンチマーキングヘルパー、 BRunParallelメソッドが追加されました。 これを使用すると、複数のCPUで簡単にベンチマークが実行できるようになります。

更新: crypto/tlsパッケージの修正は既存のコードを壊してしまうかもしれません。 しかし、そのようなコードにはバグがあるので、更新すべきです。

小規模な変更点

以下に、標準ライブラリへの小規模な変更点をまとめます。そのほとんどは新たに追加されたものです。 より詳細な情報は関係するパッケージのドキュメントを参照して下さい。