乔克视界 乔克视界
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档

乔克

云原生爱好者
首页
  • 运维
  • 开发
  • 监控
  • 安全
  • 随笔
  • Docker
  • Golang
  • Python
  • AIOps
  • 心情杂货
  • 读书笔记
  • 面试
  • 实用技巧
  • 博客搭建
友链
关于
收藏
  • 分类
  • 标签
  • 归档
  • Docker

  • Golang

    • Golang基础知识

      • 开发环境搭建
      • 常量与变量
      • 基本数据类型
      • 复合数据类型
      • 流程控制
      • 运算符
      • 位运算符详解
      • 指针
      • map
      • 函数
      • defer
        • defer 执行机
        • panic 和 recover
      • 类型别名与自定义类型
      • 结构体
      • 接口
      • 包
      • 文件操作
      • 反射
      • 并发
      • socket网络编程
      • HTTP网络编程
      • 单元测试
      • 基准测试
      • 并发测试
      • 示例函数
      • 性能优化
      • go module
      • 在Go中使用Makefile
      • 部署Go项目
    • Golang进阶知识

    • Golang常用包

  • AIOps

  • 专栏
  • Golang
  • Golang基础知识
乔克
2025-07-13
目录

defer

Go 语言中的defer语句会将其后面跟随的语句进行延迟处理。在defer归属的函数即将返回时,将延迟处理的语句按defer定义的逆序进行执行,也就是说,先被defer的语句最后被执行,最后被defer的语句,最先被执行。

如下:

package main

import "fmt"

func main() {
	fmt.Println("start")
	defer fmt.Println(1)
	defer fmt.Println(2)
	defer fmt.Println(3)
	fmt.Println("end")
}
1
2
3
4
5
6
7
8
9
10
11

输出结果如下:

start
end
3
2
1
1
2
3
4
5

由于defer语句延迟调用的特性,所以defer语句能非常方便的处理资源释放问题。比如:资源清理、文件关闭、解锁及记录时间等。

# defer 执行机

在 Go 语言的函数中return语句在底层并不是原子操作,它分为给返回值赋值和 RET 指令两步。而defer语句执行的时机就在返回值赋值操作后,RET 指令执行前。具体如下图所示:17adf2fa3b03a5429a7cf3f63cbd1c34 MD5

# panic 和 recover

在函数部分介绍了几个内部函数,其中panic和revocer是 Go 语言中用来处理错误的。

比如:

package main

import "fmt"

func f1() {
	fmt.Println("f1 func...")
}

func f2() {
	var status bool
	// 关闭数据库
	func() {
		fmt.Println("关闭数据库失败")
		status = false
	}()

	if !status {
		panic("这里出现了严重的错误")
	}
	fmt.Println("f2 func...")
}

func f3() {
	fmt.Println("f3 func...")
}
func main() {
	f1()
	f2()
	f3()
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

执行的结果如下:

f1 func
关闭数据库失败
panic: 这里出现了严重的错误

goroutine 1 [running]:
main.f2()
        E:/DEV/Go/src/code.rookieops.com/day02/defer/main.go:14 +0x40
main.main()
        E:/DEV/Go/src/code.rookieops.com/day02/defer/main.go:24 +0x85
exit status 2
1
2
3
4
5
6
7
8
9
10

上面的例子程序执行到f2函数的panic的时候就触发错误直接退出了,后面的语句和f3函数没有继续执行。如果要继续执行后面的语句就需要使用recover函数,如下:

package main

import "fmt"

func f1() {
	fmt.Println("f1 func...")
}

func f2() {
	var status bool
	// 关闭数据库
	func() {
		fmt.Println("关闭数据库失败")
		status = false
	}()

	// 用revocer()恢复
	defer func() {
		err := recover()
		if err != nil {
			fmt.Println("恢复了,继续执行后面语句")
		}
	}()

	if !status {
		panic("这里出现了严重的错误")
	}
	fmt.Println("f2 func...")
}

func f3() {
	fmt.Println("f3 func...")
}
func main() {
	f1()
	f2()
	f3()

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39

其输出的结果如下:

f1 func...
关闭数据库失败
恢复了,继续执行后面语句
f3 func...
1
2
3
4

注意:

  • recover 必须和 defer 搭配使用
  • defer 一定 要在可能引发 panic 之前定义
上次更新: 2025/07/18, 18:41:03
函数
类型别名与自定义类型

← 函数 类型别名与自定义类型→

最近更新
01
2025年,SRE在企业中可以做哪些事
07-18
02
SRE 如何提升自己在团队中的影响力
07-18
03
使用Go开发MCP服务
07-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 乔克 | MIT License | 渝ICP备20002153号 |
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式