2.1 No.1:意図しない変数シャドウイング
間違い
あるブロックで宣言された変数名は、内側のブロックでも再宣言できる。この規則は変数シャドウイングと呼ばれるが、これがよくある間違いになりがちである
下記のコード例は、client変数を宣言しているが、ifブロック内で省略変数宣言演算子(:=)を使って、関数呼び出しの結果を外側のclientではなく、内側のclientに代入している。結果、外側のclientは常にnilのままになる(コードがコンパイルされても、値を受け取る変数が期待してたものでない状況に直面する)
code:go
var client *http.Client
if tracing {
client, err := createClientWithTracing()
if err != nil {
return err
}
} else {
client, err := createDefaultClient()
if err != nil {
return err
}
}
解決策
解決のための2つの選択肢。どちらも完全に有効で選択は好みによる
一時変数を使う方法
code:go
var client *http.Client
if tracing {
c, err := createClientWithTracing()
if err != nil {
return err
}
client = c
} else {
c, err := createDefaultClient()
if err != nil {
return err
}
client = c
}
内側のブロックで代入演算子(=)を使用し、関数の結果を直接clientに代入する方法
代入演算子はすでに宣言されている場合にのみ機能するので、errの変数を作成する必要がある。この場合、if/else文の外側でエラー処理を共通化して実装もできる
code:go
var client *http.Client
var err error
if tracing {
client, err = createClientWithTracing()
} else {
client, err = createDefaultClient()
}
if err != nil {
return err
}