两个对同一个函数的 defer 调用会同时执行吗?

huangapple go评论170阅读模式
英文:

Will two defer calls for the same function be both executed?

问题

在下面的代码中,defer关键字用于延迟执行函数调用,直到包含它的函数返回为止。

package main

import "net/http"

func main() {
    resp, _ := http.Get("http://google.com")
    defer resp.Body.Close()
    resp, _ = http.Get("http://stackoverflow.com")
    defer resp.Body.Close()
}

在这段代码中,有两个HTTP GET调用,它们都将结果赋值给同一个变量respdefer关键字会将resp.Body.Close()函数调用推迟到包含它的函数(main()函数)返回之前执行。

main()函数执行完毕时,会按照defer的逆序执行已推迟的函数调用。因此,两个defer resp.Body.Close()语句都会执行,但是第二个defer语句将在第一个defer语句之前执行。也就是说,第二个defer语句将最先执行,然后是第一个defer语句。

所以,当main()函数执行完毕时,会先执行第二个defer resp.Body.Close()语句,然后再执行第一个defer resp.Body.Close()语句。

英文:

What happens to the defer in the code below?

package main

import "net/http"

func main() {
	resp, _ := http.Get("http://google.com")
	defer resp.Body.Close()
	resp, _ = http.Get("http://stackoverflow.com")
	defer resp.Body.Close()
}

There are two HTTP GET calls, both return to the same variable. Does defer stack the operation, leading to two Close() calls, or will only one be executed when main() finishes? (if the latter: will that be the first or second defer that gets executed?)

答案1

得分: 2

是的,defer 会将对变量 resp 的引用堆叠起来,导致两次 Close 调用。例如,在以下代码中,cleanUp 函数被调用两次,分别使用了不同的 A 值:

package main

import "fmt"

type Resp struct {
    A int
}

func (r *Resp) cleanUp() {
    fmt.Println("清理", r.A)
}

func main() {
    r := &Resp{1}
    defer r.cleanUp()

    fmt.Println("我在这里做一些事情!")

    r = &Resp{2}
    defer r.cleanUp()
}

上述代码的输出结果为:

我在这里做一些事情!
清理 2
清理 1

因此,即使 r 的值被覆盖,它也不会导致 defer 语句中的变量被覆盖。

英文:

Yes, the defer does stack the reference to the variable resp leading to two Close calls. For example, in the following code, the cleanUp function is called with two different A Values:

package main

import "fmt"

type Resp struct {
    A int
}

func (r *Resp) cleanUp() {
	fmt.Println("Cleaned up ", r.A)
}

func main() {
	r := &Resp{1}	
	defer r.cleanUp()	
    
    fmt.Println("I am doing something here!")

    r = &Resp{2}
	defer r.cleanUp()
}

Above code outputs:

I am doing something here!
Cleaned up  2
Cleaned up  1

Thus even though the value of r is overwritten, it doesn't lead to overwriting of variable in the defer statement.

huangapple
  • 本文由 发表于 2021年5月23日 19:59:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/67659487.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定