Golang return和defer之间的逻辑关系

150 阅读1分钟

结论:return 与 defer 的执行顺序是先执行 return,后执行 defer 函数返回值定义分为两种,一种是匿名返回值,另一种是具名返回值

匿名返回值与defer

func Sum(a, b int) int {
    var result int
    defer func() {
       result = -1
    }()
    result = a + b
    return result
}

执行 Sum(1, 2) 后打印的返回值是3,defer并没有影响到返回值。原因:在匿名返回值的函数中,执行return 时会生成一个临时变量,将 return 的结果赋值给临时变量,然后再执行 defer,defer 修改的是 result 变量,而函数返回的是临时变量,所以并不会影响到返回值

具名返回值与defer

func Sum(a, b int) (result int) {
    defer func() {
       result = -1
    }()
    result = a + b
    return result
}

我们将匿名返回值例子中 Sum 函数的返回值定义修改为具名返回值,执行 Sum(1, 2) 后打印的返回值是-1,此时 defer 却能正常修改返回值。原因:具名返回值函数会在函数执行前将具名变量(示例中的result)定义好,并且函数最终返回的就是具名变量。因此,defer 修改的是 result 具名变量,返回的变量也是具名变量 result,所以函数返回的结果就是 defer 修改后的值。(注意:return result 会将 result 变量赋值给 result 变量,然后再执行 defer)

思考以下例子的返回值 Sum(1, 2), 3 or 9?

func Sum(a, b int) (result int) {
    result = a + b
    return 9
}

结果是9,执行 return 语句时将9赋值给了具名返回值变量 result。