Go语言的坑: Shadow 变量

[toc]

1
2
3
4
5
6
7
8
9
10
11
12
13
var client *http.Client
if tracing {
client, err := createClientWithTracing()
if err != nil {
return err
}
log.Println(client)
} else {
client, err := createDefaultClient()
if err != nil {
return err
}
log.Println(client) }

在上面这段代码中,声明了一个 client 变量,然后使用 tracing 控制变量的初始化,可能是因为没有声明 err 的缘故,使用的是 := 进行初始化,那么会导致外层的 client 变量永远是 nil。这个例子实际上是很容易发生在我们实际的开发中,尤其需要注意。

如果是因为 err 没有初始化的缘故,我们在初始化的时候可以这么做:

1
2
3
4
5
6
7
8
9
10
var client *http.Client
var err error
if tracing {
client, err = createClientWithTracing()
} else {
...
}
if err != nil { // 防止重复代码
return err
}

或者内层的变量声明换一个变量名字,这样就不容易出错了。

我们也可以使用工具分析代码是否有 shadow,先安装一下工具:

1
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow

然后使用 shadow 命令:

1
2
3
4
go vet -vettool=/path/to/shadow ./main.go
# command-line-arguments
./main.go:15:3: declaration of "client" shadows declaration at line 13
./main.go:21:3: declaration of "client" shadows declaration at line 13