Go 1.4 RC1が出たのでまとめ
原文: http://tip.golang.org/doc/go1.4
- ガベージコレクタを改善したよ
goコマンドにいくつかツールが追加されたよ- Android, NaCl, AMD64上のPlan9サポートが追加されたよ。互換性も維持するよ
- MapやSliceを単純に要素分だけループさせる時にそのまま
for range {…と続けて書けるようになったよ
for range x {
// xの要素サイズ分だけループ実行
}※今まではfor _ := range x { … と書かないといけなかった
※でもシンタックスチェッカーは↑に直せっていうかもしれないよ
double dereference(訳し方わからない)に対してもメソッドがコールできるようになったよ
※これは1.4での破壊的な変更だけど、ほとんどのプログラムに影響はないと思う。
- Android、NaCl、Plan9がサポートされたよ
unsafeパッケージはGoの型システムを壊しちゃうっぽいけど、今までガイドラインでは名言してなかったよね。- なのでGoの互換性に関するガイドラインで互換性を保てないよと名言しておいた。
- ガベージコレクタとかその他いろいろはだいたいCとassemblerで書かれてたけど1.4からはほとんどGoで書き直したよ。だから実行時に変数がアクティブであるかそうでないかを正確に知ることができるようになってるよ。大規模な変更だったけど、プログラムへの影響はないよ
- これによって、プラグラム中のアクティブなポインタの位置を正確に知ることができるからヒープサイズを減らすことができるよ。大体10~30%はヒープサイズが減るよ
- (hot split問題について色々)
- 1.4ではゴルーチンのデフォルトスタックサイズは8192→2048bytesに縮小されたよ
- interface値の実装が変更されたよ。以前のリリースではスカラー値を持ってたんだけど、これがガベージコレクタの問題だったんだ。なので1.4では常にポインタを保持するようにしたよ。影響は小さいけど、例えばinterface型にintを格納するとたくさんallocateするよ
- Go1.3では有効なポインタであればメモリワードを見つけられたけど、明らかに不正なポインタだった場合はクラッシュしてたんだ。1.4では
GODEBUG変数にinvalidptr=0を指定すればクラッシュは回避できるようにしたけど、そもそもエイリアス整数とポインタを使わないコードに書き換える必要があるよ
- (アセンブラに関する記述)
- GCCのリリースとGoのリリーススケジュールは一致してないよ。1.2ではGCC4.9が含まれているけど、1.4ではおそらくGCC5を含めるよ
- Goのパッケージシステムはコンポーネント内の構造化が簡単にできるけど、内部アクセス/グローバルアクセスに関して、意図しないパッケージのエクスポートを避けたい時があるよね
- Goはこれを区別する強制力はないんだけど、1.4では
goコマンドに内部パッケージとして、外部からインポートされない定義を行うメカニズムが導入されるよ internalっている名前のディレクトリ配下に配置すると、goコマンドはそのディレクトリを親とするツリー内からしかインポートできなくなるよ
※つまり、/a/b/c/internal/d/e/f という配置の場合、 internal/以下のパッケージは/a/b/c/というツリー内のパッケージからしかインポートできない。/a/b/gというパッケージは外部扱いとしてインポートできない、ということらしい。
- Go1.4では、これは主にメインリポジトリにのみ適用されるよ。1.5からは任意のリポジトリに対して適用するつもりだよ
- コードは殆どの場合、
github.comなどのパブリックなホスティングサービス上にあるよね(例えば、github.com/rsc/pdfとか)。 - 既存のメカニズムを使うと、
rsc.io/pdfのようなカスタム、または見栄えを重視した2つのインポートパスができるんだ。これが問題で、一つのプログラムが2つの個別のパスを通してインポートされる。これは無駄だし、別のホスティングサービスに移動してしまった場合、パッケージのアップデートを見逃してしまう。 - Go1.4では正規インポートパスを識別するための注釈が導入されていくよ。もし正規のインポートパスでないものを使用すると、
goコマンドはそのインポートしたパッケージをコンパイルするのを拒否するよ - シンタックスは簡単で、
packageの行に識別用のコメントを書くだけだよ
package pdf // import "rsc.io/pdf"- この記述により、
goコマンドはgithub.com/rsc/pdfからインポートしたパッケージをコンパイルするのを拒否して、コードはユーザを壊すこと無く移動できることを保証するよ - このチェックはダウンロード時ではなくビルド時に行われるので、このチェックにより
go getが失敗するときは、インポートに失敗するパッケージはローカルマシンにコピーされていて、手動で削除しないといけないよ - この新機能を補完するのに、ローカルパッケージのリモートリポジトリがそのカスタムインポートと一致しているかどうかの確認が更新時に追加されたよ。パッケージを最初にダウンロードしてからリモートリポジトリが変更された場合には、
go get -uコマンドは失敗することになるよ。このチェックは新しい-fフラグを使えばオーバーライドされるよ
- Goプロジェクトのサブリポジトリ(
code.google.com/p/go.toolsとか)はcode.google.com/p/goを置き換えるカスタムインポートパスの下で利用可能だよ(golang.org/x/の中のgolang.org/x/toolsもそうだね) - 2015/06/01あたりに正規のインポートパスのコメントを追加するから、そのGo1.4以降は古い
code.google.comのパスは受け入れなくなるから注意してね - サブリポジトリからインポートしているコードは全て
golang.orgパスを使用するように書き換えてね。Go1.0以降は新しいインポートパスを解決できるし、この書き換えでも旧リリースとの互換性を壊すことはないよ。書き換えてないコードは2015/06/01あたりからコンパイルできなくなるよ
※パスの置換はいずれしないといけないですね
- コンパイル前にソースコードを生成するツールを実行するため、
goコマンドにgo generateっていう新しいサブコマンドができたよ - 例えば、Goの文法を実装するソースファイルを生成するため、
.yファイル上でyaccパーサジェネレータをを実行したり、golang.org/x/toolsサブリポジトリ内にある新しいstringerツールを使って、型付き定数のためにStringメソッドを自動生成したりするのに使うよ
※ユーザレベルで使いドコロあるのかな、、、
- 1.4までは
arm.goみたいにタグ付けしてたんだけど、新しいアーキテクチャが追加された時にこのタグが破壊されちゃうからビルドタグ名を変更するよ。_amd64.goみたいにアンダースコアが付いている場合のみタグ付けするよ - なので、windows.goとかamd64.goといったファイル名はタグ付けされないからコンパイルできないよ。os_window.goとかsupport_amd64.goみたいな名前に変えないといけないよ
※このあたりまだ触れてないからわかってない
- パッケージをビルドするのに
cgoコマンドを使ってない限り、関連するCコンパイラ(6cなど)は将来のリリースから削除するつもりなので、コンパイルできなくなるよ(今はruntimeパッケージのビルドに使ってる)これはどんなケースにおいても正しく使うのが難しいし、現存する用途でも使い方が間違ってるっぽいから無効にすることにしたよ - 結果のバイナリ名を指定するための、他のサブコマンドと同じく
go testに-oフラグが追加されたよ。--fileフラグは実用的じゃないから削除したよ go testコマンドはテスト関数が無くても全ての*_test.goファイルをコンパイルしてリンクするようになったよ。これは以前は無視してたんだけどねgo buildサブコマンドの-aフラグの振る舞いが非開発のインストール用に変更されたよ。リリースされているディストリビューションを実行してインストールする場合は、-aフラグはインストールファイルの上書きを避けるために、標準ライブラリやコマンドを再ビルドしないよ
- メインのGoソースリポジトリでは、パッケージのソースのコードは
/src/pkg/以下に保持されてたんだけど、これは他のサブリポジトリと異なっちゃうんだよね。1.4では、pkg階層のソースツリーは無くして、例えばfmtパッケージはsrc/pkg/fmtにあったんだけど、src/fmtの一つ上の階層に配置されるよ - godocのようなソースコードを発見するツールは新しい場所を知っておかないといけないよ。Goチームでメンテナンスしているツールとサービスは更新したよ
- このリリースに起因するランタイムの変更で、Go1.4はSWIG3.0.3が必要になるんだけどまだリリースされてないんだ。Go1.4のリリース日には多分あると思うけど
- (ツール関連の話題っぽい)
- ほとんどのプログラムは1.3に比べて同等かわずかに速く実行され、いくつかはわずかに遅くなるよ。多くの変更があって、明確に期待通りにするのは難しいね
- 上述のように、ランタイムの多くはCからGoに翻訳されて、それによりいくらかヒープサイズを減少させたよ。Cコンパイラがランタイムをビルドするより、インライン化のようなことをすることでGoのコンパイラがより最適化されたので、パフォーマンスがわずかに改善したんだ
- ガベージコレクタが高速化して、プログラムの重いゴミを測定、改善につながっているよ。一方で、新しい書き込み障壁が再びスローダウンして、典型的なその振る舞いにより、いくつかのプラグラムはやや遅く、または速くなることもあるよ
- 新しいパッケージはないよ
bufioパッケージ内のScannertypeにバグがあって、カスタムしたsplit関数を必要とすることでFIXしたよ。このバグはEOFで空のトークンが作られない問題で、split関数によって終了条件が決まる変更でFIXしたよ。以前はそれ以降のデータがなかった時はEOFでスキャンが停止してたんだ。1.4では、split関数が入力を使い果たした後に一度だけコールされるので、split関数はドキュメントで既に約束している最終的な空のトークンを生成することができるよ。- カスタム
split関数は必要に応じてEOFで空のトークンを処理する必要があるかもしれないよ
syscallパッケージはコアリポジトリを維持するために必要な変更を除いて凍結しているよ。特に、コアで使われる異なるシステムコールをサポートするようにはもう拡張しないよ。理由は別文書で説明しているからねgolang.org/x/sysという新しいサブリポジトリで、全てのカーネルでのシステムコールをサポートするために開発しているよ。それはUnix/Window/Plan9の3つそれぞれの実装を抑えるためによい構造なんだ。これらのパッケージはそれぞれのオペレーティング・システムでのカーネルインターフェースを反映して、全ての合理的な変更を受け入れるよ。ドキュメントや詳細は上述の記事を参照してね- 1.3のリリースから大幅には変更されてないので、既存の
syscallパッケージに影響はないよ。でも今後の開発でsyscallパッケージが必要なら、golang.org/x/sysを代わりに使ってね
以下のリストは小さなライブラリの変更だよ。詳しくは関連するパッケージのドキュメントを見てね
archive/zipパッケージのWriterがFlushメソッドをサポートしたよcompress/flateとcompress/gzip、compress/zlibパッケージにResetメソッドがサポートされて、バッファを再利用することでパフォーマンスが改善するよ。compress/gzipパッケージは複数のファイルストリームをコントロールするMultiStramメソッドもサポートしたよcryptoパッケージにcrypto/ecdsaとcrypto/rsaのプライベートキータイプを実装するためのSignerインターフェースができたよcrypto/tlsパッケージにRFC7301のALPNサポートが追加されたよcrypto/tlsパッケージにConfig構造体のCertificateForName関数を通してサーバ認証を行うプログラムセクションをサポートしたよ- また、
crypto/tlsパッケージで、サーバはクライアントがフォールバック攻撃を検出するのを助けるためにTLS_FALLBACK_SCSVをサポートしているよ(Goのクライアントはフォールバックを全てサポートしていないから、これらの攻撃に対しては脆弱ではないよ) database/sqlパッケージは登録されている全てのドライバをリストアップできるようになってるよdebug/dwarfパッケージは未定義の型をサポートしているよencoding/ans1パッケージ内で、デフォルト値を持っているオプション要素は省略できるよencodeing/csvパッケージは空文字をクオートしないけど、データ終了マーカ(.)はクオートするよ。これはCSVの定義によって許可されて、Postgresとの連携にとても良いよencoding/gobパッケージは安全でない操作を排除するために書き換えられて、unsafeパッケージの使用が許可されていない環境で使うことを許可するよ。典型的な使用では10-30%遅くなるけど、幾つかのデータ型に依存しているケースでの差、特に配列を含む場合は高速になるよ。機能的な変更はないよencoding/xmlパッケージのDecoderは入力オフセットを通知するようになってるよfmtパッケージ内のMapへのポインタ書式は配列や構造体の書式と一致するように変更したよ。例として、{&map[string]int{"one": 1}は16進のポインタ値ではなく&map[one: 1]`と出力するようになってるよimageパッケージのRGBAとGrayのImageの実装は全般的なAtメソッドに沿って、RGBAAtとGrayAtメソッドとして特殊になっているよimage/pngパッケージは圧縮符号化を操作するためにEncoder型を持ったよmathパッケージにNextafter32関数ができたよnet/httpパッケージのRequest型にHTTPのBASIC認証で認証リクエストを送ったユーザとパスワードを取得するBasicAuthメソッドが追加されたよnet/httpパッケージのTransport型に独自のTLS接続の開始を許可するためにDialTLSフックが追加されたよnet/http/httputilパッケージのReverseProxy型はErrorLogという新しいフィールドを持って、これはユーザがコントールできるロギングを可能にするよosパッケージのシンボリックリンクがWindowsでもSymlink関数で可能になるよ。他のオペレーティングシステムではすでにあるよ。Unsetenv関数も同じくねreflectパッケージのTypeインターフェースにComparableメソッドを追加して、これは型が一般的な比較を実装しているかどうかをレポートするよ- また、
reflectパッケージのValueインターフェースはランタイムのインターフェースの実装変更により、3から4語になったよ。これはメモリを節約できるけど、意味的な効果は無いよ runtimeパッケージのWindows上で単調なクロックを実装したよ。他のオペレーティングシステムにはもうあるねruntimeパッケージのMallocsカウンタはとても小さな割り当てをカウントするようになったよ。これはGo1.3ではしてなかったね。これはより正確な答えを得るためのReadMemStatsまたはAllocsPerRunを使ったテストを破壊するかもしれないよruntimeパッケージないのPauseEnd配列はMemStats、GCStats構造体に追加されたよ。この配列はガベージコレクション循環バッファの一時停止が終了した時の循環バッファの回数になるよ。対応する一時停止時間はすでにPauseNsに記録されているよruntime/raceパッケージがFreeBSDをサポートしたよ。よって、goコマンドの-raceフラグがFreeBSDで有効になったことになるよsync/atomicパッケージはValueという新しい型を持つよ。Valueは任意の型のアトミックな読み込みと保存のための効率的なメカニズムを提供するよ- Linuxでの
syscallパッケージ内の実装で、SetuidとSetgidが無効になっているよ。これは呼び出し元のスレッドではなく、プロセス全体で動作するようになっていて、他のプラットフォームでの期待する結果と異なっているからね testingパッケージに一連のテストセットを実行する上で制御しやすい手法がついたよ。もしテストに以下のコードが含まれている場合:
func TestMain(m *testing.M)- この関数は直接テストを実行する代わりに呼び出されます。
M構造体にはテストを実行するためのメソッドが含まれているよ - また、
testingパッケージで、新しいCoverage関数は現在のテストカバレッジの一部を報告するので、個別のテストレポートが全てのカバレッジに対してどれくらい占めているかを知ることが可能になるよ text/scannerパッケージのScanner型に新しいIsIdentRune関数が追加されて、これはスキャン時にいずれはの識別子の定義を制御することが可能になるよtext/templateパッケージのブーリアン関数のeq、lt、その他は符号付き/符号なしの整数の比較を可能にして一般化したから、使いやすくなったよ。(以前は同一符号の比較しかできなかったんだ)全ての負数は符号なしの値より小さいと比較されるよtimeパッケージはマイクロ秒を出力するためにマイクロ記号(U+00B5 'μ')の標準的な記号を使用してるよ。ParseDurationメソッドはまだus(マイクロ秒)を受け付けないけど、このパッケージはマイクロ秒をusとして出力するよ- 出力形式に依存するけど、
ParseDurationを使用していないコードは更新する必要があるよ