Go: 変数パラメータが展開されておらず、ピットを踏んでいないことを覚えておいてください
1.再発
私は当初、独自のエラー関数 test1280Error を実装し、固定プレフィックス識別子を持つエラー オブジェクトを生成したいと考えていました。
import "fmt"
func main() {
fmt.Println(test1280Error("msg: %s %s", "connection refused", "127.0.0.1:80"))
}
func test1280Error(format string, args ...interface{
}) error {
return fmt.Errorf("test1280 error: "+format, args)
}
テストでは、エラー関数 test1280Error の変数パラメーターを処理するときに、出力が期待と一致しないことがわかりました。
実際の出力:
$ go run main.go
test1280 error: msg: [connection refused 127.0.0.1:80] %!s(MISSING)
期待される出力:
$ go run main.go
test1280 error: msg: connection refused 127.0.0.1:80
2.解決する
test1280Error エラー関数の args 呼び出しを変更します。
修正する前に:
func test1280Error(format string, args ...interface{
}) error {
return fmt.Errorf("test1280 error: "+format, args)
}
変更後:
func test1280Error(format string, args ...interface{
}) error {
return fmt.Errorf("test1280 error: "+format, args...)
}
3. 理由
見落としにより、test1280Error エラー関数で変数パラメータ args が正しく展開されませんでした。
a. 変数パラメータ args にアクセスして、args[subscript] を通じて添字要素を指定できます。次に例を示します。
import "fmt"
func main() {
fmt.Println(test1280Error("msg: %s %s", "connection refused", "127.0.0.1:80"))
}
func test1280Error(format string, args ...interface{
}) error {
return fmt.Errorf("test1280 error: "+format, args[0], args[1])
}
結果:
$ go run main.go
test1280 error: msg: connection refused 127.0.0.1:80
b. 変数パラメータは args を介して展開できます...
args のパラメータの数が変化するため、args[0]、args[1]... を明示的に指定してアクセスすることができないため、上記の方法は機能しません。
変数パラメータ args がそれぞれ 1、2、および 3 であると仮定すると、args[0]=1、args[1]=2、args[2]=3 となります。
return fmt.Errorf("test1280 error: "+format, args[0], args[1], args[2])
代わりに次のコードを使用できます。
return fmt.Errorf("test1280 error: "+format, args...)
args... は、文字列置換と同様に、args[0]、args[1]、args[2] に展開されます。