Golang中的defer关键字实际上是如何工作的

Golang中的defer关键字实际上是如何工作的,go,Go,我有这个密码: defer common.LogWarning( "b09ee123-f18b-46a8-b80d-f8361771178d:", resp.Body.Close(), // gets called immediately, is *not* deferred.. ) common.LogWarning就是这样的: func LogWarning(uuid string, err error) { if err != nil { log

我有这个密码:

defer common.LogWarning(
    "b09ee123-f18b-46a8-b80d-f8361771178d:",
    resp.Body.Close(),  // gets called immediately, is *not* deferred..
)
common.LogWarning就是这样的:

func LogWarning(uuid string, err error) {
    if err != nil {
        log.Warning(uuid, err)
    }
}
问题是resp.Body.Close会立即被调用——该调用不会被延迟,那么这是如何工作的呢?为什么不延迟整个代码块?

延迟延迟函数的执行,直到当前函数返回。函数的参数将立即求值

如果需要延迟所有计算都要延迟的代码块,请将其设置为函数:

defer func() {
  // Stuff to defer here
}()
``

从:

延迟语句的行为是直接和可预测的。有三条简单的规则:

在计算DEREFER语句时,将计算DEREFER函数的参数。 延迟函数调用。函数的参数将立即求值

使用匿名函数实现您的目标:

defer func() {
    common.LogWarning("b09ee123-f18b-46a8-b80d-f8361771178d:",
          resp.Body.Close())
}()

尾随表示的调用被延迟。

为什么整个代码块不被延迟,因为这不是代码块,您正在调用Close以将返回的错误作为参数传递。这可能会有所帮助。您不了解延迟规范的哪一部分?您正在推迟对common.LogWarning的调用,但当然所有参数都会被计算。因此,在对defer语句进行计算后,会立即对它们进行计算,是的。