在golang中软瞎,我們經(jīng)常會(huì)用:=來(lái)聲明變量,這很方便但也會(huì)帶來(lái)一些問(wèn)題拉讯。當(dāng)變量遇到作用域時(shí)就容易產(chǎn)生shadowing涤浇。
比如說(shuō)我們經(jīng)常會(huì)遇到的:
shadow: declaration of "err" shadows declaration
什么是變量隱藏呢?
就是當(dāng)年在后面重新聲明了前面已經(jīng)聲明的同名變量時(shí)魔慷,后面的變量值會(huì)遮蔽前面的變量值只锭,雖然這兩個(gè)變量同名但值卻不一樣。這樣是很容易產(chǎn)生問(wèn)題的院尔。
舉個(gè)栗子來(lái)看一下:
func main() {
n := 0
if true {
n := 1
n++
}
fmt.Println(n) // 0
}
這個(gè)結(jié)果n=0
這里因?yàn)樵趇f的作用域中對(duì)n重新聲明了蜻展,所以里面的n++對(duì)外面的n并不起作用喉誊。
如果是在里面對(duì)n直接賦值而不是重新聲明呢?
func main() {
n := 0
if true {
n = 1
n++
}
fmt.Println(n) // 2
}
這里結(jié)果n=2
這么明顯的情況我們寫代碼的時(shí)候很容易發(fā)現(xiàn)纵顾,但如果是很復(fù)雜的代碼呢伍茄,尤其是遇到err的時(shí)候真的很容易Shadowing。
再舉個(gè)栗子:
func templateToFile(templateFilename string, filename string, data interface{}) (err error) {
if f, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0666); err == nil {
defer f.Close()
if t, err := template.ParseFiles(templateFilename); err == nil {
return t.Execute(f, data)
}
}
return
}
這里第一個(gè)if作用域中的err和第二個(gè)作用域中的err不是同一個(gè)東西施逾,但又是相同名的變量敷矫,所以也會(huì)造成變量遮蔽。
如何解決呢汉额,這種一般把第二個(gè)err變量改名或者用賦值代理重新聲明就可以解決了曹仗。
那對(duì)于這種變量遮蔽的情況,如何檢測(cè)呢闷愤?
情況嚴(yán)重的話你的代碼會(huì)直接編譯失敗整葡,但如果不嚴(yán)重的情況你的代碼是跑的起來(lái)的,但仍然會(huì)存在遮蔽的情況讥脐。
1遭居,可以用vet,Go 1.12 以上的版本需要
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow
go vet -vettool=$(which shadow)
2,也可以用goland的tool工具(我一般用這種)
3旬渠,還可以用golangci-lint工具,也可以檢測(cè)出來(lái)俱萍。