func TestDefer() int {
v := 1
defer func() {
v++
fmt.Println(`defer v:`, v)
}()
v = 3
return v
}
func TestDefer2() (v int) {
v = 1
defer func() {
v++
fmt.Println(`defer2 v:`, v)
}()
v = 3
return
}
func TestDefer3() (v int) {
v = 1
defer func() {
v++
fmt.Println(`defer3 v:`, v)
}()
v = 3
vv := v+1
fmt.Println(`vv:`, vv)
return vv
}
func main() {
fmt.Println(`TestDefer:`, TestDefer())
fmt.Println(`TestDefer2:`, TestDefer2())
fmt.Println(`TestDefer3:`, TestDefer3())
}
上面三种方法的输出结果:
defer v: 4
TestDefer: 3
defer2 v: 4
TestDefer2: 4
vv: 4
defer3 v: 5
TestDefer3: 5
三种例子的主要区别是返回值的初始化方式不同:
以参数形式定义返回值变量名称:则实际返回结果是在 defer 处理后的结果。
在函数内定义的变量作为返回值时,defer 不会影响最终返回结果
当我们在函数定义的时候申明了返回值类型与变量名时,函数内部直接使用 return
即可,而当返回值并没有申明变量名时,内部会自动定一个变量名,因此函数内部的 return v
并不是我们认为的 v 而是被替换了
常见的在函数内定义返回值时,内部实际执行的顺序:
# 参考上面例子1 TestDefer() int
v := 1
v = 3
# 系统内部给返回值类型 int 自动生成了变量 a 并将我们原来的 return v 中的 v 赋值给 a 返回 a
a := v
# 此时 defer 中的 v 已经和返回值没有关系了
func() {
v++
fmt.Println(`defer v:`, v)
}()
return a
等同于下面例子
# 我们定义是这样的
func TestDefer() int {
v := 1
return v
}
# 实际等同于这样的效果
func TestDefer() (a int) {
v := 1
a = v
return
}
以参数形式定义返回值时,内部实际执行的顺序:
# 参考上面例子3 TestDefer3() (v int)
v = 1
v = 3
vv := v+1
# 这里系统内部自动将我们原来的 return vv 进行赋值给自定义的返回值类型 int 对应的变量 v
v = vv
# defer 中的 v 与返回值从始至终都是同一个变量, v 执行了自增并被返回
func() {
v++
fmt.Println(`defer3 v:`, v)
}()
return