19 延迟调用(Defer)

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

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

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总会被调用。这对具有多个出口点的大型函数尤其有用。

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

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

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

  // ... more code
}

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

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

最后更新于