Skip to content

Instantly share code, notes, and snippets.

@syossan27
Created February 19, 2018 05:50
Show Gist options
  • Select an option

  • Save syossan27/767ce992f9e354f00236a18aeee1b1ee to your computer and use it in GitHub Desktop.

Select an option

Save syossan27/767ce992f9e354f00236a18aeee1b1ee to your computer and use it in GitHub Desktop.

Introduction to Go 1.10

最新のGoリリース、バージョン1.10は、Go 1.9から6ヶ月後に届きます。
その変更のほとんどは、ツールチェーン、ランタイム、およびライブラリの実装にあります。 いつものように、リリースはGo 1の互換性を約束しています。
ほとんどすべてのGoプログラムは以前と同じようにコンパイルと実行を続けます。

このリリースでは、ビルドされたパッケージのキャッシュを改善し、テスト結果のキャッシュを追加し、テスト中に自動的にvetを実行し、
cgoを使用してGoとCの間で文字列値を直接渡すことができます。
新しいコンパイラオプションホワイトリストは、古いリリースで正常に構築されたコードで予期しない無効なフラグエラーを引き起こす可能性があります。

Changes to the language

言語仕様には大きな変更はありません。

型なし定数によるシフトを含むコーナーケースが明らかになり、その結果、コンパイラはインデックス式x[1.0 << s](sは型なし定数)を許可するように更新されました。
go/typesパッケージはすでに行っています。

メソッド式の文法が更新され、型式を受信者として許可する構文が緩和されました。
コンパイラがすでに実装していたものと一致します。
たとえば、struct{io.Reader}.Readは、コンパイラがすでに受け入れており、現在は言語文法で許可されていて、もしかすると珍しい、有効なメソッド式です。

Ports

このリリースでは、サポートされる新しいオペレーティングシステムまたはプロセッサアーキテクチャはありません。
ほとんどの作業は、既存ポートのサポート強化、特にアセンブラの新しい命令とコンパイラによって生成されたコードの改善に重点を置いています。

Go1.9 リリースノートで発表されているように、Go1.10ではFreeBSD 10.3以降が必要です。
FreeBS D9.3のサポートが削除されました。

GoはNetBSDで再び動作しますが、未リリースのNetBSD 8が必要です。
GOARCH amd64と386だけが修正されました。
armポートはまだ破損しています。

32ビットMIPSシステムでは、新しい環境変数設定GOMIPS=hardfloat(デフォルト)GOMIPS=softfloatは、
浮動小数点計算にハードウェア命令またはソフトウェアエミュレーションを使用するかどうかを選択します。

Go 1.10は、OpenBSD 6.0で動作する最後のリリースです。
Go 1.11にはOpenBSD 6.2が必要です。

Go 1.10は、OSX 10.8 MountainLion、またはOS X 10.9 Mavericksで実行される最後のリリースです。
Go 1.11には、OS X 10.10 Yosemite以降が必要です。

Go 1.10は、Windows XPまたはWindows Vista上で実行される最後のリリースです。
Go 1.11にはWindows 7以降が必要です。

Tools

Default GOROOT & GOTMPDIR

環境変数 $GOROOTが設定されていない場合、go toolは以前はツールチェーンのコンパイル時にデフォルトのGOROOTを使用していました。
現在、デフォルトに戻す前に、goツールはGOROOTを独自の実行可能パスから推測します。
これによりバイナリディストリビューションをファイルシステムのどこにでも展開し、GOROOTを明示的に設定せずに使用することができます。

デフォルトでは、goツールは一時ファイルとディレクトリをシステムの一時ディレクトリに作成します(たとえばUnixでは$ TMPDIR)。
新しい環境変数$GOTMPDIRが設定されている場合、goツールは代わりにそのディレクトリに一時ファイルとディレクトリを作成します。

Build & Install

go buildコマンドは、ソースファイルの内容、指定されたビルドフラグ、コンパイルされたパッケージに格納されているメタデータに基づいて古いパッケージを検出するようになりました。
変更時間はもはや相談または関連することはありません。
ビルドフラグが変更されたなどの理由で、変更時間が誤解を招くような場合に-aを追加して強制的に再ビルドを行う、という古いアドバイスが不要になりました。 (そうでなければ、バグを報告してください。)

go build -asmflags-gcflags-gccgoflags、および-ldflagsオプションは、
デフォルトでは、コマンド行に直接リストされたパッケージにのみ適用されるようになりました。たとえば、go -gcflags = -mを実行します。
mypkgはビルド時にコンパイラに-mフラグを渡しますが、依存関係は渡しません。 新しい、より一般的な形式-asmflags=pattern=flags(および他のものについても同様)は、パターンに一致するパッケージにのみフラグを適用します。

例:go install -ldflags=cmd/gofmt=-X=main.version=1.2.3 cmd/... cmd/...と一致するすべてのコマンドをインストールしますが、
cmdgofmtのリンカフラグに-Xオプションを適用するだけです。
詳細は、go buildのヘルプを参照してください。

go buildコマンドは、$GOROOT/pkgまたは$GOPATH/pkgにインストールされたパッケージとは別に、最近ビルドされたパッケージのキャッシュを保持するようになりました。
キャッシュの効果は、明示的にパッケージをインストールしないビルドや、異なるバージョンのソースコードを切り替えるとき
(たとえば、バージョンコントロールシステムの異なるブランチ間を行き来するときなど)の速度を上げることです。

go build -igo test -iのように、速度のために-iフラグを追加するという古いアドバイスは、もはや必要ありません。
ビルドは-iを使わずに速く実行されます。 詳細は、go help cacheを参照してください。

go installコマンドは、コマンドラインに直接リストされているパッケージとコマンドだけをインストールするようになりました。
たとえば、go install cmd/gofmtgofmtプログラムをインストールしますが、依存するパッケージはインストールしません。

新しいビルドキャッシュは、将来のコマンドを、依存関係がインストールされているかのように速やかに実行します。
依存関係のインストールを強制するには、新しいgo install -iフラグを使用します。

依存パッケージをインストールする必要は一般的ではありません。
インストールされているパッケージの概念は、将来のリリースでは消えるかもしれません。

Goビルド実装の多くの詳細は、これらの改善をサポートするように変更されました。
これらの変更によって暗示される1つの新しい要件は、バイナリのみのパッケージが、バイナリのみのパッケージを使用してプログラムをリンクするときに利用できるように、
バイナリ専用パッケージがスタブソースコードで正確なインポートブロックを宣言しなければならないということです。
詳細は、go help filetypeを参照してください。

Test

go testコマンドはテスト結果をキャッシュするようになりました。
テスト実行ファイルとコマンドラインが以前の実行と一致し、その実行によって参照されるファイルと環境変数が変更されていない場合、
go testは前のテスト出力を出力し、経過時間を文字列 "(cached)"で置き換えます。

テストキャッシングは、成功したテスト結果にのみ適用されます。
明示的なパッケージリストでテストコマンドを実行するだけです。

-cpu-list-parallel-run-short、および-vの各テストフラグのサブセットを使用するコマンドラインにのみ適用されます。
テストキャッシングをバイパスする慣習的な方法は、-count=1使用することです。

go testコマンドは、テストを実行する前に重大な問題を特定するために、テストされているパッケージを自動的に実行します。
このような問題は、ビルドエラーのように扱われ、テストの実行を妨げます。
利用可能なgo vetチェックの信頼できるサブセットのみがこの自動チェックに対して有効になります。
go vetの実行を無効にするには、go test -vet=offを使用します。

go test -coverpkgフラグは、その引数をカンマで区切られたパターンのリストとして解釈して、
新たに読み込むパッケージのリストとしてではなく、各テストの依存関係と一致させるようになりました。
たとえば、go -coverpkg=allは、テストパッケージとそのすべての依存関係に対して有効なカバレッジでテストを実行するための意味のある方法です。
また、複数のテストを実行する場合、go test -coverprofileオプションがサポートされるようになりました。

タイムアウトのために失敗した場合、テストは終了する前にプロファイルを書き込む可能性が高くなります。

go testコマンドは、指定されたテストバイナリの実行からの標準出力と標準エラーを常にマージし、両方をテストの標準出力に書き込むようになりました。
これまでのリリースでは、ほとんどの場合、このマージを適用しただけでテストを行っていました。

go test -v出力には、並列テストが一時停止して続行されたときにマークするPAUSEおよびCONTステータス更新行が含まれるようになりました。

新しいgo test -failfastフラグは、テストが失敗した後に追加のテストを実行しないようにします。 失敗したテストと並行して実行されるテストは完了することができます。

最後に、新しいgo test -jsonフラグは、新しいコマンドgo tool test2jsonを使用してテスト出力をフィルタリングし、
テスト実行のJSON形式の機械可読記述を生成します。
これにより、IDEや他のツールでのテスト実行の豊富なプレゼンテーションを作成することができます。

これらの変更の詳細については、go help testtest2jsonのマニュアルを参照してください。

Cgo

#cgo CFLAGSなどを使用してcgoによって指定されたオプションは、現在許可されているオプションのホワイトリストと照合されます。
これにより、ダウンロードされたパッケージが-fpluginのようなコンパイラオプションを使用して、ビルドされているマシン上で任意のコードを実行するセキュリティホールが閉じられます。
これにより、#cgo CFLAGSに無効なフラグなどのビルドエラーが発生する可能性があります。
より多くの背景とこのエラーを処理する方法については、 https://golang.org/s/invalidflag を参照してください。

CgoはGo型エイリアスを使用して "typedef X Y"のようなC型typedefを実装するので、GoコードはC.XとC.Yを同じ意味で使用できます。
また、ニラディック関数のようなマクロの使用もサポートしています。
また、Go構造体とGo配列がcgo-exported関数の型シグネチャでサポートされていないことを明確にするために、ドキュメントが更新されました。

CgoはCからの文字列値への直接アクセスをサポートするようになりました。
Cプリアンブルの関数は、_GoString_型を使用してGo文字列を引数として受け入れることができます。
Cコードは_GoStringLen_GoStringPtrを呼び出して、文字列の内容に直接アクセスできます。
_GoString_タイプの値は、Goタイプの文字列の引数をとるエクスポートされたGo関数への呼び出しで渡すことができます。

ツールチェーンのブートストラップ中、環境変数CCとCC_FOR_TARGETは、結果のツールチェーンがホストビルドとターゲットビルドにそれぞれ使用するデフォルトのCコンパイラを指定します。
ただし、複数のターゲットでツールチェーンを使用する場合、それぞれに異なるCコンパイラを指定する必要があります (たとえば、darwin/arm64linux/ppc64leの異なるコンパイラ)。

環境変数CC_FOR_goos_goarchの新しいセットでは、ターゲットごとに異なるデフォルトのCコンパイラを指定できます。
これらの変数は、ツールチェインのブートストラップ中にのみ適用され、結果として得られるツールチェインで使用されるデフォルトを設定することに注意してください。
その後のビルド・コマンドは、CC環境変数を使用するか、組み込みのデフォルトを使用します。

Cgoは通常、Goのポインタ型にマップされるいくつかのC型を、代わりにuintptrに変換します。 これらの型には、DarwinのCoreFoundationフレームワークのCFTypeRef階層とJavaのJNIインタフェースのjobject階層が含まれます。

これらの型は、Goガベージコレクタを混乱させるので、Go側でuintptrでなければなりません。
それらは時にはポインタではなく、ポインタサイズの整数でエンコードされたデータ構造です。
Goメモリへのポインタをこれらのuintptr値に格納してはいけません。

この変更のため、影響を受ける型の値は、定数nilではなく定数0でゼロ初期化する必要があります。
Go 1.10はその書き換えに役立つgofixモジュールを提供しています:

go tool fix -r cftype <pkg>
go tool fix -r jni <pkg>

詳細については、cgoのドキュメントを参照してください。

Doc

go docツールはTまたは* Tのスライスを返す関数をT型のディスプレイに追加します。これは、単一のTまたは* Tの結果を返す関数の既存の動作と同様です。

例えば

$ go doc mail.Address
package mail // import "net/mail"

type Address struct {
	Name    string
	Address string
}
    Address represents a single mail address.

func ParseAddress(address string) (*Address, error)
func ParseAddressList(list string) ([]*Address, error)
func (a *Address) String() string
$

以前は、ParseAddressListはパッケージ概要(go doc mail)にのみ表示されていました。

Fix

go fixツールは、 "golang.org/x/net/context" のインポートを "context"に置き換えました。
(Go 1.9以降を使用している場合、前者のエイリアスを転送すると後者と完全に同等になります)

Get

go getコマンドは現在、Fossilソースコードリポジトリをサポートしています。

Pprof

runtime/pprofパッケージによって生成されたブロッキングプロファイルとmutexプロファイルにはシンボル情報が含まれているため、
プロファイルを生成したバイナリなしでgo tool pprofで表示できます。
(他のすべてのプロファイルタイプはGo 1.9のシンボル情報を含むように変更されました)

go tool pprofプロファイルビジュアライザーは、github.com/google/pprofのgit version 9e20b5b(2017-11-08)に更新されました。
これには更新されたWebインターフェイスが含まれています。

Vet

go vetコマンドは、cgoまたはvendored importを使用しているパッケージであっても、パッケージのチェック時に完全な最新のタイプ情報に常にアクセスできるようになりました。
その結果、レポートはより正確になるはずです。
go vetだけがこの情報にアクセスできることに注意してください。
より低レベルのgo tool vetはvet自身で作業する場合を除いて避けてはならず、避けるべきである。
(Go 1.9以降、go vetgo tool vetと同じフラグにアクセスできます)。

Diagnostics

このリリースには、利用可能なGoプログラム診断ツールの新しい概要が含まれています。

Gofmt

Goソースコードのデフォルトの書式設定の2つのマイナーな詳細が変更されました。
まず、以前はx[i + 1:j:k]のようにフォーマットされ、より一貫した間隔:x[i + 1:j:k]でフォーマットされた複雑な3インデックスのスライス式。
第2に、型アサーションで時々使用される単一行で書かれた単一メソッドのインターフェイスリテラルは、もはや複数の行に分割されません。

gofmtに対するこれらのマイナーな更新は、時々期待されることに注意してください。
一般的には、ソースコードが特定のバージョンのgofmtの出力と一致するかどうかを確認するシステムを構築することをお勧めします。
たとえば、リポジトリにすでにチェックインされているコードが「適切にフォーマットされていない」場合、失敗する連続的な統合テストは本質的に脆弱であり、推奨されません。

ソースファイルをフォーマットするためにどのバージョンのgofmtが使用されているかについて、複数のプログラムが同意しなければならない場合は、
同じgofmtバイナリを呼び出すように設定することでこれを行うことをお勧めします。
たとえば、Goオープンソースリポジトリでは、Git pre-commitフックがGoで書かれ、go/formatを直接インポートできますが、
代わりに現在のパスにあるgofmtバイナリが呼び出されるので、pre-commitフックは必要ありません。gofmtが変更されるたびに再コンパイルしてください。

Compiler Toolchain

コンパイラには、生成されたコードのパフォーマンスに対する多くの改善が含まれており、サポートされているアーキテクチャ全体に均等に分散されています。

バイナリに記録されたDWARFデバッグ情報は、いくつかの点で改善されました。
定数値が記録されるようになりました。
行番号情報がより正確になり、ソースレベルでのプログラムのステップ実行が向上します。
各パッケージは現在、独自のDWARFコンパイル単位として提供されています。

さまざまなビルドモードがより多くのシステムに移植されています。
特に、c-sharedはlinux/ppc64lewindows/386windows/amd64で動作するようになりました。
pieはdarwin/amd64で動作し、すべてのシステムで外部リンクを強制します。
プラグインはlinux/ppc64ledarwin/amd64で動作するようになりました。

linux/ppc64leポートでは、cgoを使用するプログラムとの外部リンクの使用が必要になります。
標準ライブラリでも使用されます。

Assembler

ARM32ビットポートの場合、アセンブラは、
BFC、BFI、BFX、BFXU、FMULAD、FMULAF、FMULSD、FMULSF、FNMULAD、FNMULAF、FNMULSD、FNMULSF、
MULAD、MULAF、MULSD、MULSF、NMULAD、NMULAF、 NMULD、NMULF、NMULSD、NMULSF、XTAB、XTABU、XTAH、およびXTAHU。

ARM 64ビットポートの場合、アセンブラは、
VADD、VADDP、VADDV、VAND、VCMEQ、VDUP、VEOR、VLD1、
VMOV、VMOVI、VMOVS、VORR、VREV32、およびVST1命令をサポートするようになりました。

PowerPC 64ビットポートの場合、アセンブラは、
POWER9命令のADDEX、CMPEQB、COPY、DARN、LDMX、MADDHD、MADDHDU、MADDLD、MFVSRLD、MTVSRDD、MTVSRWS、
PASTECC、VCMPNEZB、VCMPNEZBCC、およびVMSUMUDMをサポートするようになりました。

S390Xポートの場合、アセンブラはTMHH、TMHL、TMLH、およびTMLL命令をサポートするようになりました。

X86 64ビットポートの場合、アセンブラは、
完全なAVX、AVX2、BMI、BMI2、F16C、FMA3、SSE2、SSE3、SSSE3、SSE4.1、およびSSE4.2拡張セットを含む359の新しい命令をサポートするようになりました。

アセンブラは、予期せず条件フラグをクリアしないように、XORL命令としてもMOVL $ 0、AXを実装しません。

Gccgo

Goの半期リリーススケジュールとGCCの年間リリーススケジュールとの整合性により、GCCリリース7にはGo 1.8.3バージョンのgccgoが含まれています。
次のリリースのGCC 8にはgccgoのGo 1.10バージョンが含まれる予定です。

Runtime

LockOSThreadUnlockOSThreadへのネストされた呼び出しの動作が変更されました。
これらの関数は、goroutineが特定のオペレーティングシステムスレッドにロックされているかどうかを制御するので、
ゴルーチンはそのスレッド上でのみ実行され、スレッドはそのゴルーチンのみを実行します。
以前は、一度に複数回LockOSThreadを呼び出すのは、一度呼び出すのと同じで、
1つのUnlockOSThreadは常にスレッドをロック解除していました。

ネストが呼び出される: LockOSThreadが複数回呼び出された場合、スレッドのロックを解除するにはUnlockOSThreadを同じ回数呼び出す必要があります。
これらの呼び出しをネストしないように注意していた既存のコードは正しいままです。
ネストされた呼び出しを間違って想定していた既存のコードは正しくなります。

LockOSThreadUnlockOSThreadの一般的な使用方法の1つは、Goコードがスレッドローカルステート
(LinuxやPlan 9ネームスペースなど)を確実に変更できるようにするためです。
ランタイムはロックされたスレッドを再利用または新しいスレッドの作成には不適切とみなします。

スタックトレースには、ラッパー自体にフォールトまたはパニックが発生しない限り、暗黙のラッパー関数(以前はとマークされています)は含まれなくなりました。
その結果、Callerのような関数に渡されたスキップ数は、最適化の決定と実装の詳細に依存するのではなく、コードの構造と常に一致するようになりました。
Public Goのソースコードでこれらの関数を使用するのは、2番目のカテゴリに入ります。

ガベージコレクタは、割り当てレイテンシへの影響を軽減するように変更されました。
実行時にCPU全体のうちの小さな部分を使用するようになりましたが、それ以上の時間がかかる可能性があります。
ガベージコレクタで消費されたCPUの合計は大幅に変更されていません。

呼び出しプログラムがコンパイルされた時点で、GOROOT関数はGOROOTまたはGOROOT_FINALにデフォルトで設定されます($GOROOT環境変数が設定されていない場合)。
以前は、呼び出し元のプログラムをコンパイルしたツールチェーンがコンパイルされた時点で、GOROOTまたはGOROOT_FINALを使用していました。
GOMAXPROCSの設定には制限がありません。 (Go 1.9では限界は1024であった)

Performance

いつものように、変化は非常に一般的で多様であり、パフォーマンスに関する正確な記述は難しい。
ほとんどのプログラムは、ガベージコレクタの高速化、より良いコード生成、およびコアライブラリの最適化のために、少し速く実行する必要があります。

Garbage Collector

多くのアプリケーションでは、ガベージコレクタがアクティブなときに、割り当てレイテンシと全体的なパフォーマンスオーバーヘッドが大幅に低下します。

Core library

※変更点が多いので後ほど追記

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment