首页 > 其他分享 >Go 快速入门指南 - defer 函数

Go 快速入门指南 - defer 函数

时间:2022-12-24 18:37:01浏览次数:45  
标签:defer file 入门 err println func Go 函数

概述

一个 ​​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. 1. Go 圣经 (https://book.douban.com/subject/27044219)

Go 快速入门指南 - defer 函数_Go

标签:defer,file,入门,err,println,func,Go,函数
From: https://blog.51cto.com/u_15915979/5967429

相关文章

  • Go 快速入门指南 - panic/recover 函数
    panic​​panic​​​ 会终止程序并退出,因此只有在发生严重的错误时才会使用 ​​panic​​。例子主动触发packagemainfuncmain(){panic("someerror...")}//$go......
  • Go 快速入门指南 - 结构体
    概述​​结构体​​​ 是将零个或多个字段(变量)组合在一起的复合数据类型,类似于面向对象语言中的 ​​对象​​。结构体以及其字段都使用 可见性 规则。语法规则type......
  • Go 快速入门指南 - 嵌套结构体
    概述Go支持将多个结构体通过嵌套的方式,组成一个大的结构体,降低了单个结构体复杂度,同时提高了结构体之间组合的灵活性。例子为了省略篇幅,本小节只使用 ​​字面量​​​ ......
  • Go 快速入门指南 - 函数
    概述​​函数​​ 是将一个或者一类问题包装为一个代码块,可以被多次调用,提高代码重用性。Go函数中声明、定义、参数、返回值这些基础概念,和其他编程语言中的一致,这里不再......
  • Go 快速入门指南 - init 函数
    概述​​init()函数​​ 是一个特殊的函数,一般称为初始化函数,不能被调用。 在每个文件里面,当程序启动或者文件被作为包引用的时候,init()函数就会自动执行,一般用来做一......
  • Go 快速入门指南 - 接口和方法
    接口Go接口是隐式实现。 对于一个数据类型,无需声明它实现了哪些接口,只需要实现接口必需的方法即可。当然了,存在一个小问题就是:我们可能无意间实现了某个接口:),所以 ​......
  • Go 快速入门指南 - 判断是否实现接口
    判断是否实现接口Go里面没有 ​​implements​​ 关键字来判断一个结构体(对象)是否实现了某个接口, 要实现类似的功能,需要用到 ​​类型断言​​。类型断言//判断......
  • Go 快速入门指南 - 零值和错误
    零值当一个变量使用 ​​var​​​ 进行声明后并未进行初始化(变量后面没有赋值符 ​​=​​)操作,会默认分配一个零值(zerovalue)。不同类型对应的零值类型零值boolf......
  • Go 快速入门指南 - 类型比较
    概述​​比较运算符​​​ 用来比较两个操作数并返回一个 ​​bool​​ 值,常见的比较运算符:==等于!=不等于<小于<=小于等于>大于>=大于等于......
  • Go 快速入门指南 - goroutine
    概述goroutine是Go程序并发执行的实体,对于初学者来讲,可以简单地将 ​​goroutine​​​ 理解为一个 ​​超轻量的线程​​。当一个程序启动时,只有一个goroutine调用......