Go 对同一个函数的两个defer调用是否同时执行?
下面代码中的Go 对同一个函数的两个defer调用是否同时执行?,go,deferred,deferred-execution,Go,Deferred,Deferred Execution,下面代码中的延迟发生了什么变化 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() } 有两
延迟发生了什么变化
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()
}
有两个HTTPGET
调用,都返回同一个变量。defer
stack操作,导致两个Close()
调用,还是在main()
完成时只执行一个调用?(如果是后者:这是执行的第一个还是第二个defer
)是的,defer
确实堆栈了对变量resp
的引用,导致两个Close
调用。例如,在以下代码中,使用两个不同的A
值调用cleanUp
函数:
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()
}
以上代码输出:
I am doing something here!
Cleaned up 2
Cleaned up 1
因此,即使覆盖了r
的值,也不会导致覆盖defer
语句中的变量。答案通常是:“每次执行“defer”语句时,调用的函数值和参数都会像往常一样计算并重新保存[…]”。在您的示例中,将执行两个延迟调用;将使用每个延迟语句点处的值。这里比较棘手的部分是resp
和resp.Body
是否是一个被第二个http.Get
覆盖的struct
,或者它是一个指针,第二个http.Get
获取一个新的、不同的resp
和resp.Body
。由于http.Get每次都返回一个新指针,因此这样做是正确的。更多信息请参见链接副本。我毫不怀疑两个不同的defer
语句都将被执行。我的问题是,两者使用相同的resp
(具有不同的值),因此,如果使用了指针,则只会执行一个指针。它是否为指针并不重要。如果两次使用DEBER,则相应的方法将执行两次。我已更新了上述答案。@SaiRaviTejaK虽然执行两次并不重要,但在这种特殊情况下,它关系到正确性,最后将关闭第二次resp的两倍。请参阅:@WoJ要了解正确性,您需要使用两个不同的resp变量。看看你是否用同样的。