[インデックス 12201] ファイルの概要
このコミットは、Go言語の静的解析ツールである cmd/vet
における Printf
フォーマット文字列の誤検出を修正するものです。具体的には、%e
(指数表記) フォーマット動詞に +
フラグと精度指定 (.2
) を組み合わせた "%+5.2e"
のような形式が、cmd/vet
によって誤ってエラーとして報告される問題を解決します。この修正により、cmd/vet
は有効な Printf
フォーマットに対して不必要な警告を発しなくなります。
コミット
commit 04f110e5302f9846cb110d8fcab2666ce4220623
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Sat Feb 25 01:16:17 2012 +0800
cmd/vet: don't give error for Printf("%+5.2e", x)
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5696048
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/04f110e5302f9846cb110d8fcab2666ce4220623
元コミット内容
commit 04f110e5302f9846cb110d8fcab2666ce4220623
Author: Shenghou Ma <minux.ma@gmail.com>
Date: Sat Feb 25 01:16:17 2012 +0800
cmd/vet: don't give error for Printf("%+5.2e", x)
R=golang-dev, r
CC=golang-dev
https://golang.org/cl/5696048
---
src/cmd/vet/print.go | 2 +-\n 1 file changed, 1 insertion(+), 1 deletion(-)\n
diff --git a/src/cmd/vet/print.go b/src/cmd/vet/print.go
index e0717f8e8e..ee9a33c702 100644
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -167,7 +167,7 @@ var printVerbs = []printVerb{\
{'b', numFlag},\
{'c', "-."},\
{'d', numFlag},\
- {'e', "-."},\
+ {'e', numFlag},\
{'E', numFlag},\
{'f', numFlag},\
{'F', numFlag},\
変更の背景
Go言語の fmt
パッケージが提供する Printf
関数群は、C言語の printf
に似た強力なフォーマット機能を持っています。cmd/vet
は、Goのソースコードを静的に解析し、潜在的なバグや疑わしい構成を検出するツールです。その機能の一つに、Printf
のフォーマット文字列と引数の型が一致しているかを検証する機能があります。
このコミットが行われる前、cmd/vet
は %e
(指数表記) フォーマット動詞に対して、+
フラグ(常に符号を出力する)や精度指定(小数点以下の桁数)が組み合わされた場合に、誤ってエラーを報告していました。例えば、fmt.Printf("%+5.2e", 123.45)
のような有効なコードが、cmd/vet
によって不適切なフォーマットとしてフラグ付けされていたと考えられます。
この誤検出は、開発者が有効な Printf
フォーマットを使用しているにもかかわらず、cmd/vet
の警告に直面するという不便さを引き起こしていました。このコミットは、cmd/vet
の Printf
フォーマット検証ロジックを改善し、このような誤検出を排除することを目的としています。
前提知識の解説
cmd/vet
cmd/vet
は、Go言語の標準ツールチェーンに含まれる静的解析ツールです。コンパイル時には検出されないが、実行時に問題を引き起こす可能性のあるコードの慣用的な誤用や疑わしい構成を特定します。主なチェック項目には以下のようなものがあります。
- Printf フォーマット文字列の検証:
fmt.Printf
などの関数で使用されるフォーマット文字列が、対応する引数の型と一致しているか、また有効なフォーマット動詞やフラグが使用されているかをチェックします。 - 構造体タグの検証:
json:"..."
やxml:"..."
などの構造体タグの構文が正しいかをチェックします。 - メソッドシグネチャの検証:
Error()
メソッドを持つ型がerror
インターフェースを正しく実装しているかなどをチェックします。 - ロックの誤用:
sync.Mutex
などのロックが正しく使用されているか(例えば、ロックが解放されているか)をチェックします。
fmt.Printf
とフォーマット動詞、フラグ
Go言語の fmt
パッケージは、C言語の printf
に似た書式設定されたI/O機能を提供します。Printf
関数は、第一引数にフォーマット文字列を取り、その後に可変個の引数を取ります。フォーマット文字列内の %
で始まるシーケンスは「フォーマット動詞」と呼ばれ、対応する引数をどのように表示するかを制御します。
主要なフォーマット動詞の例:
%d
: 整数を10進数で表示%f
: 浮動小数点数を標準の浮動小数点表記で表示%e
: 浮動小数点数を科学表記(指数表記)で表示 (例:1.234500e+02
)%s
: 文字列を表示%v
: 引数のデフォルトのフォーマットで表示(任意の型に対応)
フォーマット動詞には、表示をさらに制御するための「フラグ」を組み合わせることができます。
+
フラグ: 数値の場合、常に符号を出力します(例:+123.45
)。-
フラグ: フィールド内で値を左寄せします。0
フラグ: 数値の場合、幅指定の際に先頭をゼロで埋めます。#
フラグ: 代替フォーマットを使用します(例:%#x
で0x
プレフィックスを追加)。
また、フォーマット動詞の前に「幅」や「精度」を指定することもできます。
%5d
: 少なくとも5文字の幅で表示し、必要に応じてスペースで埋めます。%.2f
: 小数点以下2桁まで表示します。%5.2e
: 少なくとも5文字の幅で、小数点以下2桁の精度で指数表記します。
src/cmd/vet/print.go
このファイルは、cmd/vet
が Printf
フォーマット文字列を検証する際のロジックを定義しています。特に、各フォーマット動詞がどのようなフラグや精度指定を受け入れるかを記述したデータ構造が含まれています。
ファイル内の printVerbs
変数は、printVerb
型の構造体のスライスであり、各要素が特定のフォーマット動詞 ('b'
, 'c'
, 'd'
, 'e'
など) と、その動詞が受け入れるフラグのパターンを定義しています。
printVerb
構造体は、動詞の文字と、その動詞に適用可能なフラグのセットを保持します。numFlag
: 数値型のフォーマット動詞(%d
,%f
,%e
など)が一般的に受け入れるフラグのセットを表す定数です。これには+
,-
,0
などのフラグが含まれます。"-."
: これは、特定の動詞が-
(左寄せ) と.
(精度) フラグのみを受け入れることを示す文字列リテラルです。
技術的詳細
cmd/vet
の Printf
フォーマット検証は、src/cmd/vet/print.go
内の printVerbs
というグローバル変数に定義されたルールに基づいて行われます。この printVerbs
は []printVerb
型のスライスで、各 printVerb
は特定のフォーマット動詞(例: 'e'
)と、その動詞がサポートするフラグの集合を関連付けています。
変更前のコードでは、'e'
フォーマット動詞に対して "-."
という文字列リテラルが関連付けられていました。これは、cmd/vet
が %e
に対して -
(左寄せ) フラグと .
(精度) フラグのみを有効なものとして認識していたことを意味します。しかし、Goの fmt
パッケージのドキュメントによると、%e
は数値型のフォーマット動詞であるため、+
(常に符号を出力) や
(負でない場合にスペースを出力) などの他の数値フラグもサポートしています。
例えば、fmt.Printf("%+5.2e", x)
のようなフォーマット文字列では、+
フラグが使用されています。変更前の cmd/vet
は、'e'
動詞が +
フラグをサポートしないと誤解していたため、この有効なフォーマットに対してエラーを報告していました。
このコミットでは、'e'
フォーマット動詞に関連付けられているフラグの定義を "-."
から numFlag
に変更しています。numFlag
は、Goの fmt
パッケージで数値型のフォーマット動詞が一般的にサポートするすべてのフラグ(+
, -
,
, 0
, #
など)を網羅する定数です。この変更により、cmd/vet
は %e
動詞が +
フラグを含むすべての標準的な数値フラグを正しくサポートすることを認識するようになり、"%+5.2e"
のような有効なフォーマットに対する誤検出が解消されます。
この修正は、cmd/vet
の正確性を向上させ、開発者が Printf
の機能をより柔軟に、かつ誤検出の心配なく利用できるようにするために重要です。
コアとなるコードの変更箇所
変更は src/cmd/vet/print.go
ファイルの1箇所のみです。
--- a/src/cmd/vet/print.go
+++ b/src/cmd/vet/print.go
@@ -167,7 +167,7 @@ var printVerbs = []printVerb{\
{'b', numFlag},\
{'c', "-."},\
{'d', numFlag},\
- {'e', "-."},\
+ {'e', numFlag},\
{'E', numFlag},\
{'f', numFlag},\
{'F', numFlag},\
具体的には、printVerbs
スライス内の 'e'
フォーマット動詞に対応するエントリの2番目の要素が "-."
から numFlag
に変更されています。
コアとなるコードの解説
src/cmd/vet/print.go
ファイルには、printVerbs
という名前の []printVerb
型のグローバル変数が定義されています。このスライスは、fmt
パッケージの Printf
関数がサポートする各フォーマット動詞に関するメタデータを含んでいます。
各 printVerb
構造体は以下の形式です。
type printVerb struct {
verb rune // フォーマット動詞の文字 (例: 'e', 'd', 's')
flags string // その動詞がサポートするフラグのセット
}
flags
フィールドは、その動詞が受け入れるフラグを示す文字列です。
numFlag
: これはprint.go
内で定義されている定数で、数値型のフォーマット動詞(%d
,%f
,%e
など)が一般的にサポートするすべてのフラグ(+
,-
,0
,#
)を表します。"-."
: これは文字列リテラルで、-
(左寄せ) と.
(精度) フラグのみをサポートすることを示します。
変更前は、'e'
(指数表記) 動詞に対して flags
が "-."
と設定されていました。これは、cmd/vet
が %e
に対して -
と .
以外のフラグ(特に +
フラグ)が使用されると、それを不正なフォーマットとして認識してしまう原因となっていました。
このコミットでは、'e'
動詞の flags
を numFlag
に変更しました。これにより、cmd/vet
は %e
が numFlag
が表すすべての標準的な数値フラグ(+
, -
,
, 0
, #
)をサポートすることを正しく認識するようになります。結果として、"%+5.2e"
のような有効なフォーマット文字列が cmd/vet
によって誤ってエラーとして報告されることがなくなりました。
この修正は、cmd/vet
の Printf
フォーマット検証ロジックの正確性を向上させ、ツールの信頼性を高める上で重要な役割を果たしています。
関連リンク
- Go CL 5696048: https://golang.org/cl/5696048
参考にした情報源リンク
- Go言語
fmt
パッケージのドキュメント: https://pkg.go.dev/fmt - Go言語
cmd/vet
のドキュメント: https://pkg.go.dev/cmd/vet - Go言語のソースコード (特に
src/cmd/vet/print.go
): https://github.com/golang/go/blob/master/src/cmd/vet/print.go - Go言語の
Printf
フォーマットに関する一般的な情報源 (例: Go by Example: String Formatting): https://gobyexample.com/string-formatting (これは一般的な参考情報であり、特定のコミットに直接関連するものではありませんが、背景知識として有用です。)