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
パッケージ内のScanner
typeにバグがあって、カスタムした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
を使用していないコードは更新する必要があるよ