使用 defer 时在函数中返回值

杨寒冬*_*杨寒冬 4 go

我在使用关于返回值的“延迟”时遇到了一些问题。我尝试以不同的方式运行一个测试函数(只有 i 的定义不同),但结果不同。所以,我对不同的返回值感到困惑。这是问题所在:

功能一:

package main
import "fmt"
func main() {
    fmt.Println("a return:", a()) // return value: 0
}

func a() int {
    var i int
    defer func() {
        i++
        fmt.Println("a defer1:", i) // print " a defer1: 1"
    }()
    return i
}
Run Code Online (Sandbox Code Playgroud)

返回值:

a defer1: 1
a return: 0
Run Code Online (Sandbox Code Playgroud)

功能二:

package main
import "fmt"

func main() {
    fmt.Println("a return:", a()) // return value: 1
}

func a() (i int) {
    defer func() {
        i++
        fmt.Println("a defer1:", i) // print " a defer1: 1"
    }()
    return i
}
Run Code Online (Sandbox Code Playgroud)

返回值:

a defer1: 1
a return: 1
Run Code Online (Sandbox Code Playgroud)

返回值之一是 0,另一个是 1。所以,问题是这两个函数之间有什么区别。

pet*_*rSO 5

这两个函数有什么区别?


Go 编程语言规范

推迟声明

“延迟”语句调用一个函数,该函数的执行被推迟到周围函数返回的那一刻。

每次执行“defer”语句时,函数值和调用的参数都会像往常一样评估并重新保存,但不会调用实际的函数。相反,在周围函数返回之前立即调用延迟函数,以与延迟相反的顺序调用。

如果延迟函数是函数字面量并且周围函数具有在字面量范围内的命名结果参数,则延迟函数可以在返回结果参数之前访问和修改结果参数。如果延迟函数有任何返回值,则在函数完成时将其丢弃。


不同之处在于一个带有命名结果参数的环绕函数

func a() (i int)
Run Code Online (Sandbox Code Playgroud)

与具有未命名结果参数的周围函数

func a() int
Run Code Online (Sandbox Code Playgroud)