【Golang】幽灵变量(Shadowed Variables)

Posted by 西维蜀黍 on 2020-07-06, Last Modified on 2021-09-21

幽灵变量(Shadowed Variables)

Example 1

如果你在新的代码块中像下边这样误用了 :=,编译不会报错,但是变量不会按你的预期工作:

func main() {
	x := 1
	println(x)		// 1
	{
		println(x)	// 1
		x := 2
		println(x)	// 2	// 新的 x 变量的作用域只在代码块内部
	}
	println(x)		// 1
}

这是 Go 开发者常犯的错,而且不易被发现。

Example 2

func main() {
    n := 0
    if true {
        n := 1
        n++
    }
    fmt.Println(n) // 0
}

The statement n := 1 declares a new variable which shadows the original n throughout the scope of the if statement.

To reuse n from the outer block, write n = 1 instead.

func main() {
    n := 0
    if true {
        n = 1
        n++
    }
    fmt.Println(n) // 2
}

Example 3

func BadRead(f *os.File, buf []byte) error {
        var err error
        for {
                n, err := f.Read(buf) // shadows the function variable 'err'
                if err != nil {
                        break // causes return of wrong value
                }
                foo(buf)
        }
        return err
}

Rescue

go vet

This analyzer check for shadowed variables. A shadowed variable is a variable declared in an inner scope with the same name and type as a variable in an outer scope, and where the outer variable is mentioned after the inner one is declared.

go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)

go-nyet

Installation

$ go get github.com/barakmich/go-nyet

这个包的运行方式有三种:目录/包/文件。对应的命令如下:

$ go-nyet ./...
# or
$ go-nyet subpackage
# or
$ go-nyet file.go

实际使用

使用方法如下:

> $GOPATH/bin/go-nyet main.go
main.go:10:3:Shadowing variable `x`

Reference