一尘不染

延期和命名返回值如何工作?

go

我刚开始学习Go,但是我对一个例子感到困惑,那就是在The Go Blog中使用defer更改命名的返回值-Defer,Panic和Recover

该示例说:

  1. 延迟函数可以读取并分配给返回函数的命名返回值。

在此示例中,延迟函数在周围函数返回后递增返回值i。因此,此函数 返回2

func c() (i int) {
    defer func() { i++ }()
    return 1
}

但正如我从A Go of Go中学到
的-命名返回值

不带参数的return语句 返回命名的返回值。这就是所谓的“裸”回报。

我在下面的代码中进行了测试,并在函数中b返回1,因为它不是上面提到的“ 无参数的返回语句 ”情况。

func a() (i int) { // return 2
    i = 2
    return
}

func b() (i int) {  // return 1 
    i = 2
    return 1
}

所以我的问题是在第一个示例中,周围的函数c有一个命名的返回值i,但是该函数c使用return 1第二个示例中的函数,无论值i是多少,我们都可以看到它应该具有return 1
。但是,为什么在i更改延迟函数后,该c函数返回值i而不是值1?

在输入问题时,我可能已经猜到了答案。是因为:

return 1

等于:

i = 1
return

在具有命名返回值变量的函数中i

请帮我确认一下,谢谢!


阅读 181

收藏
2020-07-02

共1个答案

一尘不染

defer语句将函数调用推送到列表上。周围函数返回后,将执行保存的呼叫列表。-
转到博客:延期,恐慌和恢复

理解上述陈述的另一种方式:

defer语句 函数调用压入 堆栈弹出 的已保存调用 (LIFO) 和延迟函数的堆栈在周围函数返回之前立即被调用。

 func c() (i int) {
    defer func() { i++ }()
    return 1
}

返回1后,func() { i++ }()将执行延迟。因此,按执行顺序:

  1. i = 1(返回1)
  2. i ++(延迟功能从堆栈中弹出并执行)
  3. i == 2(命名变量i的最终结果)

为了理解起见:

 func c() (i int) {
    defer func() { fmt.Println("third") }()
    defer func() { fmt.Println("second") }()
    defer func() { fmt.Println("first") }()

    return 1
}

执行顺序:

  1. i = 1(返回1)
  2. “第一”
  3. “第二”
  4. “第三”
2020-07-02