Golang中函数返回值注意点

Go语言函数返回值又两种方法,如下代码:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
func GoReturn1() int {
	a := 0
	return a
}
func GoReturn2() (a int) {
	a = 0
	return
}
func main() {
	fmt.Println("返回值1:", GoReturn1())
	fmt.Println("返回值2:", GoReturn2())
}

显然上面的函数返回值都是0没有什么不同,但是如果在函数体内加上一个defer func() ,那么就可能得到不同的结果 代码如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
func GoReturn1() int {
	a := 0
	defer func() {
		a++
	}()
	return a
}
func GoReturn2() (a int) {
	a = 0
	defer func() {
		a++
	}()
	return a
}
func main() {
	fmt.Println("返回值1:", GoReturn1())
	fmt.Println("返回值2:", GoReturn2())
}
运行结果

返回值1 0
返回值2 1

为什么返回值不同呢?

由于Go的返回机制决定的,如果函数的返回值只声明了返回值的类型

1
2
3
4
5
6
7
func GoReturn1() int {
    a:=0
    defer func(){
        a++
    }
    return a
}

这种情况下Go会创建临时变量保存返回值,然后去执行 defer 后面的函数,这样虽然defer后面的函数修改了a的值,但不会修改临时变量中的值,所以会返回0

而函数声明返回值类型时同时带上了变量名,又是什么情况呢?

1
2
3
4
5
6
7
func GoReturn2() (a int) {
	a = 0
	defer func() {
		a++
	}()
	return a
}

函数声明返回值类型时同时带上了变量名时,Go就不会创建临时变量保存返回值,而是直接返回声明时的变量,这样defer中修改了a的值.