乐趣区

关于go:Go-快速入门指南-defer

概述

一个 defer 语句就是一个一般的函数或办法调用。 defer 语句保障了不论是在失常状况下 (return 返回),
还是非正常状况下 (产生谬误, 程序终止),函数或办法都可能执行。

次要个性

  • 一个函数可定义多个 defer 语句
  • defer 表达式中的变量值在 defer 表达式定义时曾经确定
  • defer 表达式能够批改函数中的命名返回值

次要作用

  • 简化异样解决 (应用 defer + recover),防止异样与控制流混合在一起 (try … catch … finally)
  • defer 做资源开释和配置重置等收尾工作

语法规定

如果 defer 函数只有一行语句,能够省略 func() { ...} 代码块,否则就须要用 func() { ...} 代码块包起来。

多个 defer 执行程序

如果一个函数中注册了多个 defer 函数,这些函数会依照 后进先出 的程序执行 (和 的出栈程序统一)。
也就是最初注册的 defer 函数会第一个执行,而第一个注册的 defer 函数会最初执行。

例子

函数退出前打印字符

package main

func A() {defer println("A 函数执行实现")

    println("A 函数开始执行")
}

func B() {defer println("B 函数执行实现")

    println("B 函数开始执行")
}

func main() {A()
    B()}

// $ go run main.go
// 输入如下 
/**
  A 函数开始执行
  A 函数执行实现
  B 函数开始执行
  B 函数执行实现
*/

敞开文件句柄

package main

import (
    "fmt"
    "os"
)

func createFile(name string) *os.File {file, err := os.Create(name)
    if err != nil {panic(err)
    }
    return file
}

func writeFile(file *os.File) {n, err := file.WriteString("hello world")
    if err != nil {panic(err)
    } else {fmt.Printf("胜利写入 %d 个字符 \n", n)
    }
}

func closeFile(file *os.File) {err := file.Close()
    if err != nil {panic(err)
    }
}

func main() {file := createFile("/tmp/defer_test.txt")
    defer closeFile(file) // 获取到文件句柄后,第一工夫注册 defer 函数

    writeFile(file)
}

// $ go run main.go
// 输入如下 
/**
  胜利写入 11 个字符
*/

// $ cat /tmp/defer_test.txt
// 输入如下
/**
  hello world
*/

多个 defer 函数

package main

func A() {defer println("第 1 个 defer 函数")

    defer func() { // 这里为了演示 func() {...} 的语法
        defer println("第 2 个 defer 函数")
    }()

    defer println("第 3 个 defer 函数")

    println("A 函数开始执行")
}

func main() {A()
}

// $ go run main.go
// 输入如下
/**
  A 函数开始执行
  第 3 个 defer 函数
  第 2 个 defer 函数
  第 1 个 defer 函数
*/

reference

  1. Go 圣经

分割我

退出移动版