typora/note/Go/崩溃恢复.md
2024-12-12 10:48:55 +08:00

2.0 KiB
Raw Permalink Blame History

https://mp.weixin.qq.com/s/ZmfwNlq5_A2RgpUSkJQXrQ

defer

  • Go 语言提供的一种延迟调用机制defer 的运作离不开函数
  • 只有在函数(和方法)内部才能使用 defer
  • defer 关键字后面只能接函数(或方法),这些函数被称为 deferred 函数
  • defer 将它们注册到其所在 Goroutine 中,用于存放 deferred 函数的栈数据结构中,这些 deferred 函数将在执行 defer 的函数退出前按后进先出LIFO的顺序被程序调度执行
  • 无论是执行到函数体尾部返回,还是在某个错误处理分支显式 return又或是出现 panic已经存储到 deferred 函数栈中的函数,都会被调度执行

blog-heysq-1255479807.cos.ap-beijing.myqcloud.com/blog/2023-12-11-xoomgtcr.png

defer 注意事项

  • 明确哪些函数可以作为 deferred 函数有返回值的deferred函数的返回值会被自动丢弃
    • 内置函数 append、cap、len、make、new和imag不能被注册为deferred函数可以包装一层func进行调用
    • close、copy、delete、print、recover 可以被注册为deferred函数

Functions: 内置函数列表
  append cap close complex copy delete imag len 
  make new panic print println real recover
  • 注意 defer 关键字后面表达式的求值时机defer 关键字后面的表达式,是在将 deferred 函数注册到 deferred 函数栈的时候进行求值的
package main

import (
	"fmt"
)

func foo1() {
	for i := 0; i <= 3; i++ {
		defer fmt.Println(i)
	}
}

func foo2() {
	for i := 0; i <= 3; i++ {
		defer func(n int) {
			fmt.Println(n)
		}(i)
	}
}

func foo3() {
	for i := 0; i <= 3; i++ {
		defer func() {
			fmt.Println(i)
		}()
	}
}

func main() {
	fmt.Println("foo1 result:")
	foo1()
	fmt.Println("\nfoo2 result:")
	foo2()
	fmt.Println("\nfoo3 result:")
	foo3()
}

  • 知晓 defer 带来的性能损耗