Skip to content

Instantly share code, notes, and snippets.

@ysugimoto
Last active October 21, 2015 14:50
Show Gist options
  • Save ysugimoto/c1f073d7b08a542c8129 to your computer and use it in GitHub Desktop.
Save ysugimoto/c1f073d7b08a542c8129 to your computer and use it in GitHub Desktop.

Go 1.4 RC1が出たのでまとめ

原文: http://tip.golang.org/doc/go1.4

Introduction to Go 1.4 より

  • ガベージコレクタを改善したよ
  • go コマンドにいくつかツールが追加されたよ
  • Android, NaCl, AMD64上のPlan9サポートが追加されたよ。互換性も維持するよ

Changes to the language より

For-range ループ

  • MapやSliceを単純に要素分だけループさせる時にそのままfor range {…と続けて書けるようになったよ
for range x {
  // xの要素サイズ分だけループ実行
}

※今まではfor _ := range x { … と書かないといけなかった ※でもシンタックスチェッカーは↑に直せっていうかもしれないよ

**Tに対するメソッド呼び出しの許可

double dereference(訳し方わからない)に対してもメソッドがコールできるようになったよ

※これは1.4での破壊的な変更だけど、ほとんどのプログラムに影響はないと思う。

Changes to the supported operating systems and architectures より

  • Android、NaCl、Plan9がサポートされたよ

Changes to the compatibility guidelines より

  • unsafeパッケージはGoの型システムを壊しちゃうっぽいけど、今までガイドラインでは名言してなかったよね。
  • なのでGoの互換性に関するガイドラインで互換性を保てないよと名言しておいた。

Changes to the implementations and tools より

ランタイムへの変更

  • ガベージコレクタとかその他いろいろはだいたい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を指定すればクラッシュは回避できるようにしたけど、そもそもエイリアス整数とポインタを使わないコードに書き換える必要があるよ

アセンブリ

  • (アセンブラに関する記述)

gccgoのステータス

  • 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 generate サブコマンド

  • コンパイル前にソースコードを生成するツールを実行するため、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みたいな名前に変えないといけないよ

※このあたりまだ触れてないからわかってない

その他の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チームでメンテナンスしているツールとサービスは更新したよ

SWIG

  • このリリースに起因するランタイムの変更で、Go1.4はSWIG3.0.3が必要になるんだけどまだリリースされてないんだ。Go1.4のリリース日には多分あると思うけど

Miscellany

  • (ツール関連の話題っぽい)

パフォーマンス

  • ほとんどのプログラムは1.3に比べて同等かわずかに速く実行され、いくつかはわずかに遅くなるよ。多くの変更があって、明確に期待通りにするのは難しいね
  • 上述のように、ランタイムの多くはCからGoに翻訳されて、それによりいくらかヒープサイズを減少させたよ。Cコンパイラがランタイムをビルドするより、インライン化のようなことをすることでGoのコンパイラがより最適化されたので、パフォーマンスがわずかに改善したんだ
  • ガベージコレクタが高速化して、プログラムの重いゴミを測定、改善につながっているよ。一方で、新しい書き込み障壁が再びスローダウンして、典型的なその振る舞いにより、いくつかのプラグラムはやや遅く、または速くなることもあるよ

標準ライブラリの変更

新しいパッケージ

  • 新しいパッケージはないよ

主なライブラリの変更

bufio.Scanner
  • bufioパッケージ内のScanner typeにバグがあって、カスタムしたsplit関数を必要とすることでFIXしたよ。このバグはEOFで空のトークンが作られない問題で、split関数によって終了条件が決まる変更でFIXしたよ。以前はそれ以降のデータがなかった時はEOFでスキャンが停止してたんだ。1.4では、split関数が入力を使い果たした後に一度だけコールされるので、split関数はドキュメントで既に約束している最終的な空のトークンを生成することができるよ。
  • カスタムsplit関数は必要に応じてEOFで空のトークンを処理する必要があるかもしれないよ

syscall

  • syscallパッケージはコアリポジトリを維持するために必要な変更を除いて凍結しているよ。特に、コアで使われる異なるシステムコールをサポートするようにはもう拡張しないよ。理由は別文書で説明しているからね
  • golang.org/x/sysという新しいサブリポジトリで、全てのカーネルでのシステムコールをサポートするために開発しているよ。それはUnix/Window/Plan9の3つそれぞれの実装を抑えるためによい構造なんだ。これらのパッケージはそれぞれのオペレーティング・システムでのカーネルインターフェースを反映して、全ての合理的な変更を受け入れるよ。ドキュメントや詳細は上述の記事を参照してね
  • 1.3のリリースから大幅には変更されてないので、既存のsyscallパッケージに影響はないよ。でも今後の開発でsyscallパッケージが必要なら、golang.org/x/sysを代わりに使ってね

小さなライブラリの変更

以下のリストは小さなライブラリの変更だよ。詳しくは関連するパッケージのドキュメントを見てね

  • archive/zipパッケージのWriterFlushメソッドをサポートしたよ
  • compress/flatecompress/gzipcompress/zlibパッケージにResetメソッドがサポートされて、バッファを再利用することでパフォーマンスが改善するよ。compress/gzipパッケージは複数のファイルストリームをコントロールするMultiStramメソッドもサポートしたよ
  • cryptoパッケージにcrypto/ecdsacrypto/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メソッドに沿って、RGBAAtGrayAtメソッドとして特殊になっているよ
  • 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配列はMemStatsGCStats構造体に追加されたよ。この配列はガベージコレクション循環バッファの一時停止が終了した時の循環バッファの回数になるよ。対応する一時停止時間はすでにPauseNsに記録されているよ
  • runtime/raceパッケージがFreeBSDをサポートしたよ。よって、goコマンドの-raceフラグがFreeBSDで有効になったことになるよ
  • sync/atomicパッケージはValueという新しい型を持つよ。Valueは任意の型のアトミックな読み込みと保存のための効率的なメカニズムを提供するよ
  • Linuxでのsyscallパッケージ内の実装で、SetuidSetgidが無効になっているよ。これは呼び出し元のスレッドではなく、プロセス全体で動作するようになっていて、他のプラットフォームでの期待する結果と異なっているからね
  • testingパッケージに一連のテストセットを実行する上で制御しやすい手法がついたよ。もしテストに以下のコードが含まれている場合:
func TestMain(m *testing.M)
  • この関数は直接テストを実行する代わりに呼び出されます。M構造体にはテストを実行するためのメソッドが含まれているよ
  • また、testingパッケージで、新しいCoverage関数は現在のテストカバレッジの一部を報告するので、個別のテストレポートが全てのカバレッジに対してどれくらい占めているかを知ることが可能になるよ
  • text/scannerパッケージのScanner型に新しいIsIdentRune関数が追加されて、これはスキャン時にいずれはの識別子の定義を制御することが可能になるよ
  • text/templateパッケージのブーリアン関数のeqlt、その他は符号付き/符号なしの整数の比較を可能にして一般化したから、使いやすくなったよ。(以前は同一符号の比較しかできなかったんだ)全ての負数は符号なしの値より小さいと比較されるよ
  • timeパッケージはマイクロ秒を出力するためにマイクロ記号(U+00B5 'μ')の標準的な記号を使用してるよ。ParseDurationメソッドはまだus(マイクロ秒)を受け付けないけど、このパッケージはマイクロ秒をusとして出力するよ
  • 出力形式に依存するけど、ParseDurationを使用していないコードは更新する必要があるよ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment