Goでは、関数のシグネチャ内で戻り値の名前を明示的に宣言することができます。これらの値は自動的にその型のゼロ値で初期化されます。これは、多数の戻り変数を扱う際に便利で、引数なしでreturn演算子を介して値を暗黙的に「返す」ことができます。
例:
func foo() (x int, err error) { if someCheck() { x = 1 return // (1, nil)が返されます } return // xとerrが明示的に割り当てられなかった場合は(0, nil)が返されます }
細かい点:
nil)が返されます。これはロジックのエラーを隠す可能性があります。もし名前付き結果の関数内で戻り変数への割り当てがなく、単にreturnを呼び出した場合、何が返されますか?
答え: それらのゼロ値が返されます。たとえば、intの場合は0、ポインタの場合はnilです。
例:
func test() (res *MyType, code int) { return // 「return nil, 0」と同じです }
物語
金融サービスで、名前付き戻り値の関数内でエラーメッセージをエラー変数に割り当てるのを忘れました。その結果、障害が発生した際に関数がnilを返し、エラーが失われました。結果として、トランザクションの処理が壊れ、一部の操作が見逃されました。
物語
関数のリファクタリング中に新しい名前付き戻り値を追加しましたが、以前の戻り値の型との互換性に注意が払われず、ゼロ値の返却のためにテストが問題を見逃した結果、ストレージでのサイレントバグが発生しました。
物語
いくつかの補助関数で、名前付き結果を介してエラーをログに記録していましたが、戻り時だけでなくログ出力時にもそれらを扱い忘れることがあり、再現が難しいバグ(「エラーの消失」)につながりました。