Go1.2のリリースノート(日本語訳)

JavaScriptを有効にしてください

前書き

Go 1.2のリリースノートをChatGPTで日本語に翻訳しました。
Go 1.2 Release Notes

次のバージョン:Go1.3のリリースノート(日本語訳)
前のバージョン:Go1.1のリリースノート(日本語訳)
リリースノート一覧:Goリリース情報

Go 1.2の紹介

2013年4月にGoバージョン1.1 がリリースされて以来、リリーススケジュールは短縮され、リリースプロセスがより効率的になりました。このリリース、Goバージョン1.2、または略してGo 1.2は、1.1の約6ヶ月後に登場しましたが、1.1は1.0の後に1年以上かかって登場しました。短い時間スケールのため、1.2は1.0から1.1へのステップよりも小さなデルタですが、それでもいくつかの重要な開発が含まれています。これには、より良いスケジューラと1つの新しい言語機能が含まれます。もちろん、Go 1.2は互換性の約束 を守ります。Go 1.1(または1.0)で構築されたプログラムの圧倒的多数は、1.2に移行しても何の変更もなく動作しますが、言語の一部に制限が導入されたため、既に誤っているコードが露呈する可能性があります(nilの使用 の議論を参照)。

言語の変更

仕様を強化するために、1つのコーナーケースが明確化され、プログラムに影響を与えます。また、1つの新しい言語機能があります。

nilの使用

言語は現在、安全性の理由から、nilポインタの特定の使用がランタイムパニックを引き起こすことを保証しています。例えば、Go 1.0では、次のようなコードがあるとします。

go
1
2
3
4
5
6
7
8
9
type T struct {
    X [1<<24]byte
    Field int32
}

func main() {
    var x *T
    ...
}

nilポインタxはメモリに誤ってアクセスするために使用される可能性がありました:式x.Fieldはアドレス1<<24のメモリにアクセスする可能性があります。このような安全でない動作を防ぐために、Go 1.2では、nilポインタを介した間接参照(ここで示されているようなものだけでなく、配列へのnilポインタ、nilインターフェース値、nilスライスなど)を行うと、パニックが発生するか、正しい安全な非nil値が返されることが保証されます。要するに、nilアドレスの評価を明示的または暗黙的に要求する式はエラーです。この動作を強制するために、コンパイルされたプログラムに追加のテストが挿入されることがあります。詳細は設計文書 にあります。

更新:
古い動作に依存していたほとんどのコードは誤っており、実行時に失敗します。そのようなプログラムは手動で更新する必要があります。

三つのインデックスを持つスライス

Go 1.2では、既存の配列またはスライスをスライス操作する際に、長さだけでなく容量も指定する機能が追加されました。スライス操作は、既に作成された配列またはスライスの連続したセクションを記述することによって新しいスライスを作成します:

go
1
2
var array [10]int
slice := array[2:4]

スライスの容量は、再スライス後でもスライスが保持できる最大要素数であり、基になる配列のサイズを反映しています。この例では、スライス変数の容量は8です。Go 1.2では、スライス操作で長さだけでなく容量も指定できる新しい構文が追加されました。2番目のコロンが容量値を導入し、これはソーススライスまたは配列の容量以下でなければなりません。例えば、

go
1
slice = array[2:4:7]

このスライスは以前の例と同じ長さですが、容量は5要素(7-2)に制限されます。この新しいスライス値を使用して、元の配列の最後の3つの要素にアクセスすることはできません。この三インデックス表記では、最初のインデックスが欠落している場合([:i:j])、デフォルトでゼロになりますが、他の2つのインデックスは常に明示的に指定する必要があります。将来のGoのリリースでは、これらのインデックスのデフォルト値が導入される可能性があります。詳細は設計文書 にあります。

更新:
これは既存のプログラムに影響を与えない後方互換性のある変更です。

実装とツールの変更

スケジューラのプリエンプション

以前のリリースでは、永遠にループしているゴルーチンが同じスレッド上の他のゴルーチンを飢えさせる可能性がありました。これは、GOMAXPROCSが1つのユーザースレッドしか提供しない場合に深刻な問題です。Go 1.2では、これは部分的に解決されています:スケジューラは関数に入る際に時折呼び出されます。これにより、(インライン化されていない)関数呼び出しを含むループはプリエンプトされ、他のゴルーチンが同じスレッドで実行できるようになります。

スレッド数の制限

Go 1.2では、単一のプログラムがアドレス空間内に持つことができるスレッドの総数に対する設定可能な制限(デフォルト10,000)が導入され、いくつかの環境でのリソース飢餓問題を回避します。ゴルーチンはスレッドに多重化されるため、この制限は直接ゴルーチンの数を制限するものではなく、システムコールで同時にブロックされる可能性のある数を制限します。実際には、この制限に達するのは難しいです。新しいSetMaxThreads 関数は、runtime/debug パッケージ内でスレッド数制限を制御します。

更新:
制限に影響を受ける関数はほとんどありませんが、プログラムが制限に達して終了する場合、SetMaxThreadsを呼び出してより高いカウントを設定するように変更できます。さらに良いのは、プログラムをリファクタリングしてスレッドをより少なく必要とし、カーネルリソースの消費を減らすことです。

スタックサイズ

Go 1.2では、ゴルーチンが作成されるときのスタックの最小サイズが4KBから8KBに引き上げられました。多くのプログラムは古いサイズでパフォーマンスの問題を抱えており、パフォーマンスクリティカルなセクションで高価なスタックセグメントの切り替えを引き起こす傾向がありました。新しい数値は経験的なテストによって決定されました。反対側では、新しい関数SetMaxStackruntime/debug パッケージ内で単一のゴルーチンのスタックの最大サイズを制御します。デフォルトは64ビットシステムで1GB、32ビットシステムで250MBです。Go 1.2以前では、暴走する再帰がマシン上のすべてのメモリを消費するのがあまりにも簡単でした。

更新:
最小スタックサイズの増加により、多くのゴルーチンを持つプログラムがより多くのメモリを使用する可能性があります。回避策はありませんが、将来のリリースの計画には、この問題に対処する新しいスタック管理技術が含まれています。

CgoとC++

cgo コマンドは、リンクされたライブラリの一部がC++で書かれている場合にC++コンパイラを呼び出すようになりました。詳細はドキュメント にあります。

Godocとvetがgo.toolsサブリポジトリに移動

両方のバイナリはまだ配布に含まれていますが、godocとvetコマンドのソースコードはgo.tools サブリポジトリに移動しました。また、godocプログラムのコアはlibrary に分割され、コマンド自体は別のディレクトリ にあります。この移動により、コードを簡単に更新できるようになり、ライブラリとコマンドに分離することで、ローカルサイトや異なるデプロイメント方法のためにカスタムバイナリを構築しやすくなります。

更新:
godocとvetはライブラリの一部ではないため、クライアントGoコードはそのソースに依存しておらず、更新は必要ありません。golang.org から入手可能なバイナリ配布にはこれらのバイナリが含まれているため、これらの配布を使用するユーザーには影響がありません。ソースからビルドする場合、ユーザーは「go get」を使用してgodocとvetをインストールする必要があります。(バイナリは通常の場所にインストールされ続け、$GOPATH/binにはインストールされません。)

bash
1
2
$ go get code.google.com/p/go.tools/cmd/godoc
$ go get code.google.com/p/go.tools/cmd/vet

gccgoのステータス

将来のGCC 4.9リリースには、Go 1.2を完全にサポートするgccgoが含まれると予想しています。現在の(4.8.2)GCCリリースでは、gccgoはGo 1.1.2を実装しています。

gcコンパイラとリンカの変更

Go 1.2には、gcコンパイラスイートの動作にいくつかの意味的な変更があります。ほとんどのユーザーには影響がありません。cgo コマンドは、リンクされるライブラリにC++が含まれている場合に動作します。詳細はcgo ドキュメントを参照してください。gcコンパイラは、プログラムにパッケージ句がない場合、その起源の名残を示していました:ファイルがパッケージmainにあると仮定していました。過去は消去され、パッケージ句がない場合はエラーになります。ARMでは、ツールチェーンは「外部リンク」をサポートしており、これはgcツールチェーンで共有ライブラリを構築し、必要な環境で動的リンクサポートを提供するためのステップです。ARMのランタイムでは、5aを使用して、ランタイム内部のm(マシン)およびg(ゴルーチン)変数をR9およびR10を直接使用して参照することが可能でした。現在では、それらを正しい名前で参照する必要があります。また、ARMでは、5lリンカ(sic)がMOVBSおよびMOVHS命令をMOVBおよびMOVHの同義語として定義しており、符号付きおよび符号なしのサブワード移動の分離を明確にしています。符号なしバージョンはすでにUサフィックスで存在していました。

テストカバレッジ

go test の主要な新機能の1つは、テストカバレッジ結果を計算し、新しくインストールされた「go tool cover」プログラムの助けを借りて表示できることです。カバーツールはgo.tools サブリポジトリの一部です。次のコマンドを実行することでインストールできます:

bash
1
$ go get code.google.com/p/go.tools/cmd/cover

カバーツールは2つのことを行います。まず、「go test」に-coverフラグが与えられると、自動的に実行され、パッケージのソースを書き換え、計装ステートメントを挿入します。テストは通常通りにコンパイルされ実行され、基本的なカバレッジ統計が報告されます:

bash
1
2
3
$ go test -cover fmt
ok      fmt 0.060s  coverage: 91.4% of statements
$

次に、より詳細なレポートのために、「go test」の異なるフラグがカバレッジプロファイルファイルを作成し、「go tool cover」で呼び出されたカバープログラムがそれを分析できます。カバレッジ統計を生成および分析する方法の詳細は、次のコマンドを実行することで確認できます:

bash
1
2
$ go help testflag
$ go tool cover -help

go docコマンドの削除

「go doc」コマンドは削除されました。godoc ツール自体は削除されていませんが、go コマンドによるラッピングが削除されました。これが行っていたのは、パッケージパスによってパッケージのドキュメントを表示することだけであり、godoc自体がより柔軟にそれを行います。そのため、ドキュメントツールの数を減らし、godocの再構築の一環として、将来のより良いオプションを奨励するために削除されました。

更新:
ディレクトリで$ go docを実行する正確な機能がまだ必要な人のために、その動作は$ godoc .を実行するのと同じです。

goコマンドの変更

go get コマンドには、-tフラグが追加され、パッケージ自体だけでなく、パッケージによって実行されるテストの依存関係をダウンロードするようになりました。デフォルトでは、以前と同様に、テストの依存関係はダウンロードされません。

パフォーマンス

標準ライブラリにはいくつかの重要なパフォーマンス改善があります。以下はその一部です。

compress/bzip2 は約30%速く解凍します。crypto/des パッケージは約5倍速くなっています。encoding/json パッケージは約30%速くエンコードします。WindowsおよびBSDシステムでのネットワークパフォーマンスは、Go 1.1でLinuxおよびOS Xで行われたのと同様に、ランタイムに統合されたネットワークポーラーの使用により約30%速くなっています。

標準ライブラリの変更

archive/tarおよびarchive/zipパッケージ

archive/tar およびarchive/zip パッケージには、既存のプログラムを壊す可能性のあるセマンティクスの変更があります。問題は、これらのパッケージがos.FileInfo インターフェースの実装を提供していましたが、そのインターフェースの仕様に準拠していなかったことです。特に、Nameメソッドはエントリのフルパス名を返していましたが、インターフェース仕様ではメソッドがベース名(最終パス要素)のみを返すことを要求しています。

更新:
この動作は新たに実装されたものであり、少し曖昧であるため、壊れた動作に依存するコードはない可能性があります。もし依存するプログラムがある場合、それらは手動で特定して修正する必要があります。

新しいencodingパッケージ

新しいパッケージencoding があり、標準のエンコーディングインターフェースのセットを定義しています。これらは、encoding/xmlencoding/json 、およびencoding/binary などのパッケージのためにカスタムマーシャラーおよびアンマーシャラーを構築するために使用できます。これらの新しいインターフェースは、標準ライブラリのいくつかの実装を整理するために使用されました。新しいインターフェースは、BinaryMarshalerBinaryUnmarshalerTextMarshaler 、およびTextUnmarshaler と呼ばれます。パッケージのドキュメント および別の設計文書 に詳細があります。

fmtパッケージ

fmt パッケージのフォーマットされた印刷ルーチン(例えばPrintf )は、フォーマット仕様でインデックス操作を使用することにより、印刷されるデータ項目を任意の順序でアクセスできるようになりました。フォーマットのために引数リストから引数を取得する場所では、値をフォーマットするための値として、または幅や仕様の整数として、新しいオプションのインデックス表記[n]が引数nを取得します。nの値は1から始まります。このようなインデックス操作の後、通常の処理によって次に取得される引数はn+1になります。例えば、通常のPrintf呼び出し

go
1
fmt.Sprintf("%c %c %c\n", 'a', 'b', 'c')

は文字列"a b c"を作成しますが、このようなインデックス操作を使用すると、

go
1
fmt.Sprintf("%[3]c %[1]c %c\n", 'a', 'b', 'c')

結果は"c a b"になります。[3]インデックスは3番目のフォーマット引数である’c’をアクセスし、[1]は最初の引数’a’をアクセスし、その後の次の取得はその後の引数’b’をアクセスします。この機能の動機は、ローカリゼーションのために引数を異なる順序でアクセスするプログラム可能なフォーマットステートメントですが、他の用途もあります:

go
1
log.Printf("trace: value %v of type %[1]T\n", expensiveFunction(a.b[c]))

更新:
フォーマット仕様の構文の変更は厳密に後方互換性があり、動作中のプログラムには影響しません。

text/templateおよびhtml/templateパッケージ

text/template パッケージには、Go 1.2でいくつかの変更があります。これらはhtml/template パッケージにも反映されています。まず、基本型を比較するための新しいデフォルト関数があります。関数の名前と関連する比較演算子を示す表を以下に示します。

名前 演算子
eq ==
ne !=
lt <
le <=
gt >
ge >=

これらの関数は、対応するGo演算子とは少し異なる動作をします。まず、基本型(bool、int、float64、stringなど)にのみ作用します。(Goは、特定の状況下で配列や構造体の比較も許可します。)次に、値が同じ種類の値である限り、値を比較できます。例えば、任意の符号付き整数値は他の符号付き整数値と比較できます。(Goはint8とint16の比較を許可していません。)最後に、eq関数(のみ)は、最初の引数を1つ以上の後続の引数と比較することを許可します。この例のテンプレートは、

go
1
{{if eq .A 1 2 3}} equal {{else}} not equal {{end}}

.Aが1、2、または3のいずれかと等しい場合に「equal」と報告します。2つ目の変更は、文法に小さな追加があり、「if else if」チェーンを簡単に書くことができるようになったことです。次のように書く代わりに、

go
1
{{if eq .A 1}} X {{else}} {{if eq .A 2}} Y {{end}} {{end}}

2番目の「if」を「else」に折りたたんで、1つの「end」のみを持つことができます:

go
1
{{if eq .A 1}} X {{else if eq .A 2}} Y {{end}}

2つの形式は効果が同じであり、違いは構文だけです。

更新:
「else if」変更も比較関数も既存のプログラムには影響しません。すでにeqなどの関数を関数マップを通じて定義しているプログラムは影響を受けません。関連する関数マップが新しいデフォルト関数定義をオーバーライドするためです。

新しいパッケージ

2つの新しいパッケージがあります。

encoding パッケージは上記で説明 されています。image/color/palette パッケージは標準のカラーパレットを提供します。

ライブラリの小さな変更

以下のリストは、ライブラリのいくつかの小さな変更をまとめたもので、主に追加です。各変更についての詳細は、関連するパッケージのドキュメントを参照してください。

archive/zip

アーカイブ内のファイルの(圧縮されている可能性のある)データのオフセットを返すDataOffset アクセサを追加しました。

bufio

ReaderWriterReset メソッドを追加しました。これらのメソッドにより、ReadersWriters を新しい入力および出力リーダーおよびライターで再利用し、割り当てのオーバーヘッドを節約できます。

compress/bzip2

連結されたアーカイブを解凍できるようになりました。

compress/flate

WriterReset メソッドを追加し、例えば複数の圧縮ファイルを保持するアーカイブを構築する際に割り当てを削減できるようにしました。

compress/gzip

Writer 型は、再利用できるようにReset を追加しました。

compress/zlib

Writer 型も、再利用できるようにReset を追加しました。

container/heap

アイテムの位置をヒープ内で更新するためのより効率的な方法を提供するFix メソッドを追加しました。

container/list

明らかな再配置を実装するMoveBefore およびMoveAfter メソッドを追加しました。

crypto/cipher

新しいGCMモード(Galois Counter Mode)を追加しました。これはほとんど常にAES暗号化と共に使用されます。

crypto/md5

パフォーマンスを犠牲にせずにハッシュ化を簡素化する新しいSum 関数を追加しました。同様に、

crypto/sha1

新しいSum 関数を追加しました。

crypto/sha256

Sum256 およびSum224 関数を追加しました。

crypto/sha512

Sum512 およびSum384 関数を追加しました。

crypto/x509

任意の拡張の読み書きをサポートします。

crypto/tls

TLS 1.1、1.2、およびAES-GCMをサポートします。

database/sql

データベースへのオープン接続の数を制限するためのSetMaxOpenConns メソッドをDB に追加しました。

encoding/csv

フィールドの末尾のカンマを常に許可するようになりました。

encoding/gob

構造体のチャネルおよび関数フィールドを、エクスポートされていないかのように扱うようになりました。つまり、それらを完全に無視します。以前はエラーを引き起こし、埋め込まれた構造体がそのようなフィールドを追加した場合に予期しない互換性の問題を引き起こす可能性がありました。このパッケージは、上記で説明したencoding パッケージの一般的なBinaryMarshalerおよびBinaryUnmarshalerインターフェースもサポートするようになりました。

encoding/json

文字列を印刷する際にアンパサンドを常に「\u0026」としてエスケープするようになりました。また、Marshal で無効なUTF-8を受け入れ、修正するようになりました(以前はそのような入力は拒否されていました)。最後に、上記で説明したencoding パッケージの一般的なエンコーディングインターフェースをサポートするようになりました。

encoding/xml

ポインタに格納された属性をマーシャルできるようになりました。また、上記で説明したencoding パッケージの一般的なエンコーディングインターフェースを、新しいMarshalerUnmarshaler 、および関連するMarshalerAttr およびUnmarshalerAttr インターフェースを通じてサポートします。このパッケージは、カスタムエンコーダーで使用するためにEncoder 型にFlush メソッドも追加しました。EncodeToken のドキュメントを参照して、その使用方法を確認してください。

flag

フラグの値を取得するためのGetter インターフェースが追加されました。Go 1の互換性ガイドラインのため、このメソッドは既存のValue インターフェースに追加できませんが、既存の標準フラグ型はすべてこれを実装しています。このパッケージは、コマンドラインからのフラグを保持するCommandLine フラグセットもエクスポートします。

go/ast

SliceExpr 構造体には、新しいブールフィールドSlice3が追加され、3つのインデックス(二つのコロン)を持つスライス式を表すときにtrueに設定されます。デフォルトはfalseで、通常の2インデックス形式を表します。

go/build

ビルドタグを処理しやすくするためにPackage 型にAllTagsフィールドを追加しました。

image/draw

標準のDraw メソッドをラップするDrawer インターフェースをエクスポートするようになりました。ポーターダフ演算子はこのインターフェースを実装し、明示的に提供するのではなく、描画演算子に操作をバインドします。パレット画像を宛先として与えると、新しいFloydSteinberg 実装がDrawer インターフェースを使用して、フロイド・スタインバーグ誤差拡散アルゴリズムを使用して画像を描画します。そのような処理に適したパレットを作成するために、新しいQuantizer インターフェースは、フルカラー画像を与えられたときにパレットを選択する量子化アルゴリズムの実装を表します。このインターフェースの実装はライブラリにはありません。

image/gif

新しいEncode およびEncodeAll 関数を使用してGIFファイルを作成できるようになりました。オプション引数は使用する画像Quantizer を指定します。nilの場合、生成されたGIFは新しいimage/color/palette パッケージで定義されたPlan9 カラーマップ(パレット)を使用します。オプションは、出力画像を作成するために使用するDrawer も指定します。nilの場合、フロイド・スタインバーグ誤差拡散が使用されます。

io

Copy メソッドは、引数の優先順位を異なるようにしました。1つの引数がWriterTo を実装し、もう1つがReaderFrom を実装している場合、CopyWriterTo を呼び出して作業を行い、一般的に中間バッファリングを減らします。

net

ホストオペレーティングシステムが一般的にネットワークコールのセットアップを仲介する必要があるため、デフォルトでcgoを必要とします。ただし、いくつかのシステムでは、cgoなしでネットワークを使用することが可能であり、動的リンクを回避するために役立ちます。新しいビルドタグnetgo(デフォルトではオフ)は、可能なシステムで純粋なGoでネットパッケージを構築することを可能にします。
net パッケージは、デュアルIPスタックを使用したTCP接続セットアップのためにRFC 6555 で説明されているように、Dialer 構造体に新しいフィールドDualStackを追加しました。

net/http

RFC 6265 に従って不正なクッキーを送信しなくなりました。エラーをログに記録し、何も送信しません。
また、net/http パッケージのReadResponse 関数は、*Requestパラメータをnilにすることを許可し、その場合はGETリクエストを仮定します。最後に、HTTPサーバーは、ハンドラーコードで特別なケースを必要とせずにHEADリクエストを透過的に処理するようになりました。HEADリクエストを処理する際、HandlerResponseWriter への書き込みはServer によって吸収され、HTTP仕様で要求されるようにクライアントは空のボディを受け取ります。

os/exec

Cmd.StdinPipe メソッドは、io.WriteCloserを返しますが、その具体的な実装をos.Fileからos.Fileを埋め込む非公開型に変更し、返された値を安全に閉じることができるようになりました。Go 1.2以前では、この変更が修正する避けられない競合状態がありました。*os.Fileのメソッドにアクセスする必要があるコードは、wc.(interface{ Sync() error })のようなインターフェース型アサーションを使用できます。

runtime

SetFinalizer のファイナライザ関数の制約を緩和しました:実際の引数は、関数の形式の型に代入可能な任意の型にすることができます。これはGoの通常の関数呼び出しの場合と同様です。

sort

新しいStable 関数があり、安定したソートを実装します。ただし、通常のソートアルゴリズムよりも効率が悪いです。

strings

bytes パッケージとの一貫性のためにIndexByte 関数を追加しました。

sync/atomic

引数をポインタに格納された値と原子的に交換し、古い値を返す新しいスワップ関数セットを追加しました。関数はSwapInt32SwapInt64SwapUint32SwapUint64SwapUintptr 、およびSwapPointer であり、これはunsafe.Pointerを交換します。

syscall

Darwin用にSendfile を実装しました。

testing

TB インターフェースをエクスポートするようになりました。これは、T およびB 型と共通のメソッドを記録し、テストとベンチマーク間でコードを共有しやすくします。また、AllocsPerRun 関数は、初期化によって引き起こされるエラーを丸め、結果をより再現可能にするために、戻り値を整数に量子化するようになりました(ただし、型はfloat64のままです)。

text/template

html」などの「エスケープ」関数の引数を評価する際にポインタ値を自動的にデリファレンスし、「printf」などの他の印刷関数の動作と一致させるようになりました。

time

Parse 関数とFormat メソッドが、歴史的な日付「1871-01-01T05:33:02+00:34:08」のように、秒を含むタイムゾーンオフセットを処理するようになりました。また、これらのルーチンのフォーマットでのパターンマッチングはより厳密になりました:標準の単語「Jan」や「Mon」の後には、非小文字の文字が続かなければなりません。

unicode

元のIsOneOf と同等ですが、使いやすいIn を追加し、文字がUnicodeカテゴリのメンバーであるかどうかを確認します。


スポンサーリンク

共有

もふもふ
著者
もふもふ
プログラマ。汎用系→ゲームエンジニア→Webエンジニア→QAエンジニア