[インデックス 12530] ファイルの概要
このコミットは、Go言語の標準ツールであるgofmt
をsrc
およびmisc
ディレクトリ以下のファイルに対して実行し、コードのフォーマットを統一したものです。特に、構造体リテラルの初期化における&
演算子の省略と、for range
ループにおけるインデックスのみの使用に焦点を当てた変更が含まれています。
コミット
commit 56cae1c2307be5895c628b66f7b2418d56278f98
Author: Robert Griesemer <gri@golang.org>
Date: Thu Mar 8 10:48:51 2012 -0800
all: gofmt -w -s src misc
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5781058
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/56cae1c2307be5895c628b66f7b2418d56278f98
元コミット内容
all: gofmt -w -s src misc
R=golang-dev, rsc
CC=golang-dev
https://golang.org/cl/5781058
変更の背景
このコミットの主な目的は、Go言語のコードベース全体で一貫したコーディングスタイルを強制することです。gofmt
はGo言語の公式なフォーマッタであり、コードの可読性を高め、スタイルに関する議論を減らすために設計されています。特に-s
オプションは、より簡潔なコードを生成するための簡略化(simplification)を適用します。このコミットは、Go言語の進化に伴い、より新しい、より簡潔な構文が推奨されるようになったことを反映しています。具体的には、構造体リテラルでポインタを生成する際の&
の省略や、for range
ループで値を使用しない場合の_
の省略が挙げられます。これにより、コードの冗長性が減り、よりGoらしい(idiomatic Go)記述に近づきます。
前提知識の解説
gofmt
とは
gofmt
は、Go言語のソースコードを自動的にフォーマットするツールです。Go言語のツールチェインに標準で含まれており、Goコミュニティ全体で一貫したコーディングスタイルを維持するために広く利用されています。gofmt
は、インデント、スペース、改行などの基本的なフォーマットだけでなく、特定のコードパターンをより簡潔な形式に書き換える「簡略化(simplification)」機能も持っています。
gofmt
のオプション
-w
: フォーマット結果を元のファイルに書き込みます。このオプションがない場合、gofmt
はフォーマット結果を標準出力に出力します。-s
: コードを簡略化(simplify)します。これは、より簡潔で慣用的なGoの書き方に変換する機能です。このコミットでは、特に以下の2つの簡略化が適用されています。- 構造体リテラルにおける
&
の省略: Go 1から、構造体リテラルを初期化する際に、その構造体のポインタを返す場合、&StructType{...}
のように&
を明示的に記述する必要がなくなりました。代わりにStructType{...}
と記述するだけで、コンパイラが自動的にポインタを生成します。これは、構造体リテラルが直接ポインタ型として使用される文脈(例: スライスやマップの要素、関数の引数など)で有効です。 for range
ループにおける_
の省略:for range
ループでインデックスと値の両方を受け取る場合、for i, v := range collection
のように記述します。しかし、インデックスのみが必要で値が不要な場合、以前はfor i, _ := range collection
のように値を_
(ブランク識別子)で破棄していました。Go 1.4以降、インデックスのみが必要な場合はfor i := range collection
と記述するだけでよくなりました。これにより、不要な_
を記述する必要がなくなり、コードがより簡潔になります。
- 構造体リテラルにおける
Go言語の慣用的な書き方 (Idiomatic Go)
Go言語には、コミュニティで広く受け入れられている特定のコーディングスタイルやパターンがあります。これを「慣用的なGo(Idiomatic Go)」と呼びます。gofmt
は、この慣用的なスタイルを自動的に適用することで、Goコードの可読性と保守性を高めるのに貢献しています。このコミットで行われた変更は、当時のGo言語の慣用的な書き方に合わせてコードベースを更新する作業の一環です。
技術的詳細
このコミットは、gofmt -w -s src misc
コマンドの実行結果を反映しています。具体的には、以下の2種類のコード簡略化が広範囲に適用されています。
-
構造体リテラルの
&
演算子省略:- 変更前:
&Package{Name: "Go", Kind: "go"}
- 変更後:
{Name: "Go", Kind: "go"}
これは、構造体リテラルがポインタ型として使用される文脈において、&
演算子を省略できるようになったGoの言語仕様の変更(または推奨されるスタイル)を反映しています。コンパイラが文脈からポインタが必要であることを判断し、自動的にポインタを生成します。これにより、コードがより簡潔になります。
- 変更前:
-
for range
ループにおけるブランク識別子_
の省略:- 変更前:
for i, _ := range peers
- 変更後:
for i := range peers
これは、for range
ループでインデックスのみが必要で、値が不要な場合に、ブランク識別子_
を明示的に記述する必要がなくなったことを反映しています。Go 1.4以降、インデックスのみが必要な場合はfor i := range collection
と記述することが推奨されています。これにより、コードの冗長性が排除されます。
- 変更前:
これらの変更は、機能的な振る舞いには影響を与えません。純粋にコードのスタイルと簡潔性を向上させるためのものです。gofmt -s
は、このような簡略化を自動的に識別し、適用する能力を持っています。
コアとなるコードの変更箇所
このコミットでは、複数のファイルにわたって同様のパターンで変更が加えられています。以下に主要な変更箇所を抜粋し、そのパターンを示します。
misc/dashboard/app/build/init.go
および misc/dashboard/app/build/test.go
--- a/misc/dashboard/app/build/init.go
+++ b/misc/dashboard/app/build/init.go
@@ -15,7 +15,7 @@ import (
// defaultPackages specifies the Package records to be created by initHandler.
var defaultPackages = []*Package{
- &Package{Name: "Go", Kind: "go"},
+ {Name: "Go", Kind: "go"},
}
// subRepos specifies the Go project sub-repositories.
--- a/misc/dashboard/app/build/test.go
+++ b/misc/dashboard/app/build/test.go
@@ -37,7 +37,7 @@ const testPkg = "code.google.com/p/go.test"
var testPackage = &Package{Name: "Test", Kind: "subrepo", Path: testPkg}
var testPackages = []*Package{
- &Package{Name: "Go", Path: ""},
+ {Name: "Go", Path: ""},
testPackage,
}
ここでは、&Package{...}
という構造体リテラルの初期化が、{...}
という形式に簡略化されています。これは、defaultPackages
やtestPackages
が[]*Package
型(Package
構造体へのポインタのスライス)であるため、コンパイラが自動的にポインタを生成できる文脈であるためです。
src/pkg/crypto/tls/handshake_server_test.go
および src/pkg/exp/norm/maketables.go
--- a/src/pkg/crypto/tls/handshake_server_test.go
+++ b/src/pkg/crypto/tls/handshake_server_test.go
@@ -143,7 +143,7 @@ func testServerScript(t *testing.T, name string, serverScript [][]byte, config *
if peers != nil {
gotpeers := <-pchan
if len(peers) == len(gotpeers) {
- for i, _ := range peers {
+ for i := range peers {
if !peers[i].Equal(gotpeers[i]) {
t.Fatalf("%s: mismatch on peer cert %d", name, i)
}
--- a/src/pkg/exp/norm/maketables.go
+++ b/src/pkg/exp/norm/maketables.go
@@ -577,7 +577,7 @@ type decompSet [4]map[string]bool
func makeDecompSet() decompSet {
m := decompSet{}
- for i, _ := range m {
+ for i := range m {
m[i] = make(map[string]bool)
}
return m
@@ -646,7 +646,7 @@ func printCharInfoTables() int {
fmt.Println("const (")
for i, m := range decompSet {
sa := []string{}
- for s, _ := range m {
+ for s := range m {
sa = append(sa, s)
}
sort.Strings(sa)
これらの変更では、for range
ループでインデックスi
のみが使用され、値が使用されていない箇所で、ブランク識別子_
が省略されています。for i, _ := range collection
がfor i := range collection
に簡略化されています。
src/pkg/database/sql/sql_test.go
このファイルでは、nullTestRow
構造体の初期化において、nullTestRow{...}
が{...}
に簡略化されています。これは、nullTestRow
が配列の要素として直接使用されており、その文脈でポインタが不要であるため、構造体リテラルの&
が省略されたものと考えられます。
--- a/src/pkg/database/sql/sql_test.go
+++ b/src/pkg/database/sql/sql_test.go
@@ -463,48 +463,48 @@ type nullTestSpec struct {
func TestNullStringParam(t *testing.T) {
spec := nullTestSpec{"nullstring", "string", [6]nullTestRow{
- nullTestRow{NullString{"aqua", true}, "", NullString{"aqua", true}},
- nullTestRow{NullString{"brown", false}, "", NullString{"", false}},
- nullTestRow{"chartreuse", "", NullString{"chartreuse", true}},
- nullTestRow{NullString{"darkred", true}, "", NullString{"darkred", true}},
- nullTestRow{NullString{"eel", false}, "", NullString{"", false}},
- nullTestRow{"foo", NullString{"black", false}, nil},
+ {NullString{"aqua", true}, "", NullString{"aqua", true}},
+ {NullString{"brown", false}, "", NullString{"", false}},
+ {"chartreuse", "", NullString{"chartreuse", true}},
+ {NullString{"darkred", true}, "", NullString{"darkred", true}},
+ {NullString{"eel", false}, "", NullString{"", false}},
+ {"foo", NullString{"black", false}, nil},
}}
nullTestRun(t, spec)
}
コアとなるコードの解説
このコミットにおけるコードの変更は、Go言語のgofmt -s
コマンドによって自動的に適用される「簡略化」の典型例です。
-
構造体リテラルの
&
省略: Go言語では、構造体リテラルを初期化する際に、その構造体のポインタが必要な文脈(例:[]*MyStruct
のようなポインタのスライスに要素を追加する場合)では、&MyStruct{...}
と記述することでポインタを生成します。しかし、Goのコンパイラは賢く、文脈からポインタが必要であることを推論できる場合、&
を省略してMyStruct{...}
と記述することを許可しています。この簡略化は、コードの視覚的なノイズを減らし、より簡潔な記述を可能にします。このコミットでは、Package
構造体のポインタのスライスを初期化する際に、この簡略化が適用されています。 -
for range
ループにおける_
の省略:for range
ループは、スライス、配列、文字列、マップ、チャネルなどのコレクションをイテレートするために使用されます。通常、for index, value := range collection
のように、インデックスと値の両方を受け取ります。しかし、インデックスのみが必要で値が不要な場合、またはその逆の場合、不要な要素をブランク識別子_
で破棄することが一般的でした(例:for i, _ := range collection
)。Go 1.4以降、インデックスのみが必要な場合はfor i := range collection
と記述することが、より慣用的なスタイルとして推奨されるようになりました。これにより、コードの意図がより明確になり、不要な_
の記述が削減されます。このコミットでは、複数のテストファイルやユーティリティファイルで、この簡略化が適用されています。
これらの変更は、Go言語の進化と、よりクリーンで慣用的なコードを奨励するgofmt
の役割を明確に示しています。機能的な変更は一切なく、純粋にコードの見た目とスタイルに関する改善です。
関連リンク
- gofmt - Go Documentation
- Effective Go - gofmt
- Go 1.4 Release Notes - for range (
for range
の変更に関する言及がある可能性)
参考にした情報源リンク
- Go言語のgofmtコマンドについて - Qiita (一般的な
gofmt
の解説) - Go言語のfor文とrange式 - Qiita (
for range
の解説) - Go言語の構造体リテラル - Qiita (構造体リテラルの解説)
- golang/go GitHub Repository
- Go Code Review Comments - gofmt
- Go 1 Release Notes (構造体リテラルの
&
省略に関する情報がある可能性) - Go 1.4 Release Notes (
for range
の_
省略に関する情報がある可能性)