# 19 延迟调用(Defer)

在一个复杂函数中，很容易忘记释放资源（例如，关闭文件句柄或释放互斥锁）。

您可以使用`defer`语句，将释放资源的代码放在获取资源的代码的附近：

```go
func foo() {
  f, err := os.Open("myfile.txt")
  if err != nil {
    return
  }
  defer f.Close()

  // ... lots of code
}
```

上述例子中，`defer f.Close()`确保了`f.Close()`会在`foo`退出之前被调用。

把`defer f.Close()`紧跟着`os.Open()`放置，使得代码审查变得轻松，可核实`Close`总会被调用。这对具有多个出口点的大型函数尤其有用。

如果需要延迟调用的代码比较复杂，您可以使用函数字面量：

```go
func foo() {
  mutex1.Lock()
  mutex2.Lock()

  defer func() {
    mutex2.Unlock()
    mutex1.Unlock()
  }()

  // ... more code
}
```

您也可以使用多个`defer`语句，它们会被逆序调用，例如第一个声明的`defer`语句会在最后执行。

即便发生了`panic`，延迟函数也会被调用。


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://denglj.gitbook.io/essential-go/19-defer.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
