# 1. defer 基础概念 🌟

defer 是 Go 语言提供的一种用于注册延迟调用的机制,它保证了在函数返回之前,延迟调用一定会被执行。这使得 defer 语句非常适合进行资源清理、文件关闭等操作。

# 1.1 基本使用

func main() {
    defer fmt.Println("defer")  // 后执行
    fmt.Println("main")        // 先执行
}
// 输出:
// main
// defer

# 1.2 多个 defer 的执行顺序

defer 语句的执行顺序遵循 LIFO(后进先出)原则,类似于栈的操作。

func main() {
    defer fmt.Println("1")
    defer fmt.Println("2")
    defer fmt.Println("3")
}
// 输出:
// 3
// 2
// 1

# defer 的执行时机

defer 语句会在函数返回之前执行,因此可以在函数中做一些清理工作,比如关闭文件、释放资源等。

package main
import "fmt"
func main() {
    defer fmt.Println("defer")
    fmt.Println("main")
}

输出结果为:

main
defer

# defer 的参数

defer 语句的参数在定义时就已经确定,而不是在执行时确定。
在声明 defer 时,其参数会被求值,并保存在 defer 栈中,因此即使之后变量发生变化,defer 调用的参数值不会改变

package main
import "fmt"
func main() {
    i := 0
    defer fmt.Println(i)
    i++
}

输出结果为:

0

# defer 修改返回值的条件

  • 当函数有命名返回值时,defer 语句可以修改返回值。
  • 当函数没有命名返回值时,defer 语句不能修改返回值。
func main() {
	fmt.Println("命名返回值:", DeferTest())
	fmt.Println("无命名返回值:", DeferTest2())
}
// 如果使用命名返回值,defer 可以修改它,从而影响最终返回值
func DeferTest() (result int) {
	defer func() {
		result += 1
	}()
	result = 5
	return // 等价于 return result
}
//defer 可以修改局部变量,但不会影响返回值(如果不是命名返回值)
func DeferTest2() int {
	result := 0
	defer func() {
		result += 1
	}()
	result = 5
    //return result 会导致 result 被拷贝一份,defer 修改的是拷贝的值,而不是原值
	return result 
}

输出结果为:

命名返回值: 6
无命名返回值: 5

关键在于:

  • 命名返回值:defer 可以修改最终的返回值,因此它直接访问的就是返回值变量
  • 无命名返回值:defer 修改的是返回值变量的副本,因此它修改的并不是最终的返回值

# defer 与 return 的执行顺序

func f() int {
    defer fmt.Println("defer")
    fmt.Println("return")
    return 1
}

输出:

return 
defer

总结 :先算 return, 后跑 defer, 再真返回。

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

ZJM 微信支付

微信支付

ZJM 支付宝

支付宝