[インデックス 14425] ファイルの概要
このコミットは、Go言語の標準ライブラリであるarchive/zip
、crypto/tls
、net/http
パッケージ内のテストコードにおける出力フォーマットの誤りを修正するものです。具体的には、fmt.Printf
系の関数(t.Fatalf
やt.Errorf
など)のフォーマット文字列と引数の型が一致していない箇所を修正しています。これらのエラーは、Goの静的解析ツールであるgo vet
によって検出されました。
コミット
commit 4f250132f734f3686e1bff3b632e4598a82931a8
Author: Robin Eklind <r.eklind.87@gmail.com>
Date: Fri Nov 16 17:24:43 2012 -0800
archive/zip, crypto/tls, net/http: Fix print format errors.
All of the errors were located using "go vet ./..." in "src/pkg".
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/6856056
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/4f250132f734f3686e1bff3b632e4598a82931a8
元コミット内容
archive/zip, crypto/tls, net/http: Fix print format errors.
All of the errors were located using "go vet ./..." in "src/pkg".
R=golang-dev, iant
CC=golang-dev
https://golang.org/cl/6856056
変更の背景
この変更の背景には、Go言語のコード品質と堅牢性を向上させるという目的があります。fmt.Printf
系の関数におけるフォーマット文字列と引数の不一致は、実行時に予期せぬ出力やパニックを引き起こす可能性があります。特にテストコードにおいては、エラーメッセージの正確性がデバッグの効率に直結するため、このような問題は早期に修正されるべきです。
go vet
ツールは、このような潜在的なバグや疑わしいコードパターンを静的に検出するために設計されています。このコミットは、go vet
をsrc/pkg
ディレクトリ以下のすべてのパッケージに対して実行した結果として検出されたエラーを修正したものです。これにより、Go標準ライブラリのテストコードの信頼性が向上し、将来的な開発における同様の問題の発生を未然に防ぐことができます。
前提知識の解説
Go言語のfmt
パッケージとフォーマット動詞
Go言語のfmt
パッケージは、フォーマットされたI/O(入力/出力)を実装するための機能を提供します。Printf
、Sprintf
、Errorf
などの関数は、C言語のprintf
に似たフォーマット文字列を使用して、様々な型の値を整形して出力することができます。
フォーマット文字列には、値をどのように表示するかを指定する「フォーマット動詞(verb)」が含まれます。主要なフォーマット動詞には以下のようなものがあります。
%v
: 値のデフォルトフォーマット。任意の型に対応し、構造体なども表示できます。%s
: 文字列(string)型。%d
: 10進数整数(decimal integer)型。%q
: Goの構文で安全に引用符で囲まれた文字列(string)またはバイトスライス([]byte)。%T
: 値の型名。
これらのフォーマット動詞と、実際に渡される引数の型が一致しない場合、go vet
は警告を発します。例えば、整数を期待する%d
に文字列を渡したり、文字列を期待する%s
に整数を渡したりすると、実行時に予期せぬ結果(例: %!s(int=123)
のような出力)になったり、パニックが発生する可能性があります。
go vet
ツール
go vet
は、Go言語のソースコードを静的に解析し、潜在的なバグや疑わしい構成を報告するツールです。コンパイル時には検出されないが、実行時に問題を引き起こす可能性のあるコードパターンを特定するのに役立ちます。
go vet
が検出する一般的な問題には以下のようなものがあります。
Printf
系のフォーマット文字列と引数の不一致: 本コミットで修正された問題です。- 到達不能なコード: 常に実行されないコードパス。
- ロックの誤用:
sync.Mutex
などのロックが正しく使用されていない場合。 - 構造体タグの誤り:
json:"field_name"
のような構造体タグの構文エラー。 - 未使用の変数やインポート: コンパイラが警告を出す場合もありますが、
go vet
はより詳細な分析を行います。
go vet ./...
というコマンドは、現在のディレクトリとそのサブディレクトリにあるすべてのGoパッケージに対してgo vet
を実行することを意味します。このツールは、Go開発者がコードの品質と信頼性を維持するために広く利用されています。
技術的詳細
このコミットは、主にGoのテストフレームワークであるtesting
パッケージのt.Fatalf
およびt.Errorf
関数におけるフォーマット文字列の修正に焦点を当てています。これらの関数は内部的にfmt.Printf
と同様のメカニズムを使用しており、フォーマット動詞と引数の型が一致している必要があります。
具体的な修正内容は以下の通りです。
-
archive/zip/zip_test.go
:t.Fatal("error closing zip writer: %v", err)
をt.Fatalf("error closing zip writer: %v", err)
に変更。t.Fatal
は引数をそのまま出力するのに対し、t.Fatalf
はfmt.Sprintf
のようにフォーマット文字列と引数を解釈します。この変更により、err
が正しく%v
としてフォーマットされるようになります。
t.Fatal("got %v, expected ErrFormat", err)
をt.Fatalf("got %v, expected ErrFormat", err)
に変更。- 上記と同様の理由です。
-
crypto/tls/prf_test.go
:t.Errorf("#%d: bad master secret %s, want %s", s, test.masterSecret)
をt.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
に変更。- 元のコードでは、最初の
%d
に対応する引数がs
(文字列)になっていました。これは型が不一致です。修正後は、ループインデックスであるi
(整数)が渡されるようになり、%d
とi
の型が一致します。
- 元のコードでは、最初の
-
net/http/transfer_test.go
:t.Fatalf(
first Read = %n (%q), %v; want 3 ("foo"), n, got, err)
をt.Fatalf(
first Read = %d (%q), %v; want 3 ("foo"), n, got, err)
に変更。%n
というフォーマット動詞はGoのfmt
パッケージには存在しません。これはおそらくタイプミスで、整数n
を表示するために%d
が意図されていました。%d
に修正することで、n
の値が正しく10進数として表示されるようになります。
t.Fatalf(
second Read = %n (%q), %v; want 3 ("bar"), n, got, err)
をt.Fatalf(
second Read = %d (%q), %v; want 3 ("bar"), n, got, err)
に変更。- 上記と同様の修正です。
これらの修正は、Goのfmt
パッケージのフォーマットルールに厳密に従うことで、テスト出力の正確性を保証し、go vet
による警告を解消することを目的としています。
コアとなるコードの変更箇所
--- a/src/pkg/archive/zip/zip_test.go
+++ b/src/pkg/archive/zip/zip_test.go
@@ -186,12 +186,12 @@ func testInvalidHeader(h *FileHeader, t *testing.T) {
t.Fatalf("error writing content: %v", err)
}
if err := z.Close(); err != nil {
- t.Fatal("error closing zip writer: %v", err)
+ t.Fatalf("error closing zip writer: %v", err)
}
b := buf.Bytes()
if _, err = NewReader(bytes.NewReader(b), int64(len(b))); err != ErrFormat {
- t.Fatal("got %v, expected ErrFormat", err)
+ t.Fatalf("got %v, expected ErrFormat", err)
}
}
--- a/src/pkg/crypto/tls/prf_test.go
+++ b/src/pkg/crypto/tls/prf_test.go
@@ -51,7 +51,7 @@ func TestKeysFromPreMasterSecret(t *testing.T) {
masterSecret := masterFromPreMasterSecret(test.version, in, clientRandom, serverRandom)
if s := hex.EncodeToString(masterSecret); s != test.masterSecret {
- t.Errorf("#%d: bad master secret %s, want %s", s, test.masterSecret)
+ t.Errorf("#%d: bad master secret %s, want %s", i, s, test.masterSecret)
continue
}
--- a/src/pkg/net/http/transfer_test.go
+++ b/src/pkg/net/http/transfer_test.go
@@ -20,13 +20,13 @@ func TestBodyReadBadTrailer(t *testing.T) {
n, err := b.Read(buf[:3])
got := string(buf[:n])
if got != "foo" || err != nil {
- t.Fatalf(`first Read = %n (%q), %v; want 3 ("foo")`, n, got, err)
+ t.Fatalf(`first Read = %d (%q), %v; want 3 ("foo")`, n, got, err)
}
n, err = b.Read(buf[:])
got = string(buf[:n])
if got != "bar" || err != nil {
- t.Fatalf(`second Read = %n (%q), %v; want 3 ("bar")`, n, got, err)
+ t.Fatalf(`second Read = %d (%q), %v; want 3 ("bar")`, n, got, err)
}
n, err = b.Read(buf[:])
コアとなるコードの解説
archive/zip/zip_test.go
このファイルでは、t.Fatal
がt.Fatalf
に修正されています。t.Fatal
は引数をそのままログに出力し、テストを終了させます。一方、t.Fatalf
はfmt.Sprintf
のようにフォーマット文字列と引数を解釈し、フォーマットされたメッセージをログに出力してからテストを終了させます。元のコードでは%v
というフォーマット動詞が使われていましたが、t.Fatal
はこれを解釈しないため、意図したエラーメッセージが出力されませんでした。t.Fatalf
に変更することで、err
変数の内容が正しく%v
フォーマットで表示されるようになります。
crypto/tls/prf_test.go
ここでは、t.Errorf
の引数が修正されています。元のコードでは、#%d
というフォーマット動詞に対して文字列型の変数s
が渡されていました。これは型不一致であり、go vet
によって検出されます。修正後は、ループのインデックスである整数型の変数i
が渡されるようになり、%d
と引数の型が一致するようになりました。これにより、エラーメッセージが正しくフォーマットされ、どのテストケースでエラーが発生したかが明確になります。
net/http/transfer_test.go
このファイルでは、t.Fatalf
のフォーマット文字列内の%n
が%d
に修正されています。%n
はGoのfmt
パッケージには存在しないフォーマット動詞であり、これはタイプミスである可能性が高いです。n
は読み込んだバイト数を示す整数値であるため、10進数整数を表す%d
が正しいフォーマット動詞です。この修正により、n
の値が正しく数値として表示されるようになり、テストの出力が意図通りになります。
これらの変更はすべて、Goの標準ライブラリのテストコードにおける出力の正確性と、go vet
による静的解析の指摘事項への対応を目的としています。
関連リンク
- Go言語の
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt - Go言語の
testing
パッケージのドキュメント: https://pkg.go.dev/testing go vet
コマンドのドキュメント: https://pkg.go.dev/cmd/vet
参考にした情報源リンク
- Go言語の公式ドキュメント
go vet
に関する一般的な情報源fmt.Printf
のフォーマット動詞に関する情報源- GitHubのコミットページ: https://github.com/golang/go/commit/4f250132f734f3686e1bff3b632e4598a82931a8
- Gerrit Code Review (golang.org/cl/6856056): https://golang.org/cl/6856056