1 前言
有时候编译Go项目会出现GO err is shadowed during return的问题,是因为作用域导致变量重名,return时不是你预期的变量导致的。
2 样例
这里先复现问题,然后进行问题说明。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//test.go package main import "fmt" import "strconv" func foo(x string) (ret int, err error) { if true { ret, err := strconv.Atoi(x) if err != nil { return } } return ret, nil } func main() { fmt.Println(foo( "123" )) } |
运行:
OK,问题复现了,下面进行问题分析。
1
2
3
4
5
6
7
8
9
|
func foo(x string) (ret int, err error) { //返回值列表定义了ret和err变量,作用域是整个函数体 if true { //新的语句块 ret, err := strconv.Atoi(x) //这里又定义了新的变量ret和err,和返回值列表重名了。作用域是if语句块 if err != nil { return //这里的return语句会导致外层的ret和err被返回,而不是if语句里的ret和err } } return ret, nil } |
来自网上的解释:
It's a new scope, so a naked return returns the outer err, not your inner err that was != nil.
So it's almost certainly not what you meant, hence the error.
下面进行修改(只需要保证局部变量和全局变量不重名即可):
3 解决方案
1
2
3
4
5
6
7
8
9
10
11
12
|
func foo(x string) (ret int, err error) { if true { ret1, err1 := strconv.Atoi(x) if err1 != nil { err = err1 return } ret = ret1 } return ret, nil } |
运行:
另一种解决方法:
声明新的变量, 避免重新实例化err.