1简介在Go语言的开发中,我们可能会遇到“返回时隐藏错误”的错误。Go编码时很难发现这个错误。在GoLand中,只有变量名会高亮显示。在编译Go项目时,Go编译器返回的err在return期??间被隐藏。在本文中,我们将介绍为什么会出现此错误,以及我们应该如何解决?2、为什么会出现这个错误?示例代码:packagemainimport("errors""log")funcmain(){err:=foo()iferr!=nil{log.Printf("err=%v\n",err)return}}funcfoo()(err错误){如果err:=bar();err!=nil{return//编译器报告:err在return期??间被隐藏}returnnil}funcbar()error{err:=errors.New("thisisbar'serr")returnerr}输出结果:./main.go:18:3:errisshadowedduringreturn看了上面的代码,当我们编译代码的时候,编译器返回错误“errisshadowed返回期间”。因为函数funcfoo()(errerror)的返回值是一个命名参数,它的作用域是函数foo()的函数体,在函数体中,if分支使用短变量声明重新声明变量err,其作用域为if分支。if分支中声明的变量err与外层变量err的内存地址不同,而if分支中return返回的是外层变量err,所以if分支中的变量err被外层变量err遮蔽,导致Go编译器在编译Go项目时返回错误“errisshadowedduringreturn”。3.如何解决?阅读Part02后,读者朋友们已经明白了错误的原因。其实这个错误归结为我们没有真正掌握围棋的基础知识。你为什么这么说?因为在我们的公众号历史篇中,已经介绍了Go变量声明、作用域、函数等基础知识。如果读者朋友们彻底掌握了这些基础知识,大概率不会遇到“errisshadowedduringreturn”的错误。解决这个错误也比较简单。错误的原因是变量被遮蔽了。我们可以通过使用不同的变量名轻松避免这个错误。示例代码:...funcfoo()(errerror){iferr1:=bar();err1!=nil{return}returnnil}...但是使用不同的变量名真的能解决问题吗?我们用不同的变量名运行代码,确实Go编译器没有返回错误,我们可以正常编译Go项目。细心的读者可能已经发现,这种方案虽然可以避免Go编译器返回的错误,但是并没有将错误传递给外层变量err。因此,我们还需要将新变量err1的值赋给外层变量err,代码如下:...funcfoo()(errerror){iferr1:=bar();err1!=nil{err=err1return}returnnil}...现在,我们已经彻底解决了这个问题。修改后的代码既不会导致Go编译器返回错误,也不会传递错误信息。读者朋友们,如果你有代码“洁癖”,你一定觉得这样写代码太不优雅了。那么,有没有优雅的解决方案呢?答案是有更优雅的解决方案。我们在变量作用域一文中也提到了。在具有命名返回值的函数中,如果在函数体的不同范围内使用同名变量,则不能直接返回。相反,您需要返回后跟变量名。funcfoo()(errerror){iferr:=bar();err!=nil{returnerr}returnnil}看上面的代码,我们在if分支的范围内,后面跟return变量名err也可以解决问题,而且比用不同的更优雅变量名。现在,我们已经了解了两种解决方案。然而,这还没有结束。在我们的示例代码中,调用函数bar有一个返回值。在实际项目开发中,调用函数也可能有多个返回值。packagemainimport("errors""log")funcmain(){err:=foo()iferr!=nil{log.Printf("err=%v\n",err)return}}funcfoo()(errerror){如果代码,err:=bar();err!=nil{log.Printf("code=%verr=%v\n",code,err)return//编译器报告:err在返回期间被隐藏}returnnil}funcbar()(int,error){err:=errors.New("thisisbar'serr")return200,err}输出结果:./main.go:19:3:errisshadowedDuringreturn阅读上面的代码,调用函数bar()是多返回值。对于调用函数有多个返回值的情况,除了我们已经提到的两种方案之外,还有其他的方案。...funcfoo()(errerror){varcodeintifcode,err=bar();err!=nil{log.Printf("code=%verr=%v\n",code,err)return}returnnil}...阅读上面的代码,我们单独声明新的变量代码,而不是使用用于声明新变量代码的短变量,以避免变量err被重新声明。4.小结本文介绍Go语言编译报错errisshadowedduringreturn的原因及解决方法。首先介绍了错误产生的原因,然后介绍了三种解决错误的方法。需要注意的是,我们示例代码中的foo函数是一个命名返回值,本文介绍的方案不适用于返回值匿名的函数。参考:https://groups.google.com/g/golang-nuts/c/HmmZXC7KcVw?pli=1https://go.dev/ref/spec#Short_variable_declarations
