go语言中defer,defer的执行时机,非命名返回值和命名返回值的区别

Go语言中的 defer 语句会将其后面跟随的语句进行延迟处理。
先被defer的语句最后被执行,最后被defer的语句最先被执行。

package main
import ("fmt")
func main()  {
	fmt.Println("开始")
	defer fmt.Println("1")
	defer fmt.Println("2")
	fmt.Println("结束")
} 

开始
结束
2
1

defer语言的执行时机

go-1png

defer在函数中的使用(非命名返回值)

package main
import ("fmt")
func f2() int {
	var a =10
	// 这里使用 defer
	defer func(){
		a++
	}()
	return a
}
func main()  {
	fmt.Println(f2())
} 

输出:10

defer在函数中的使用(命名返回值 + defer 执行时机)

package main
import ("fmt")
func f2() (a int){
	defer func(){
		a++
	}()
	return a
}
func main()  {
	fmt.Println(f2())
} 

输出的值是:1
分析:
考察的是:命名返回值 + defer 执行时机
func f2() (a int) {}这里 a 是命名返回值;
它相当于在函数开头隐式声明了一个变量 a;
并且这个 a 是函数返回时实际返回的那个变量。
return 不是原子操作;
return a 在底层其实分为两步:
1,赋值:把要返回的值赋给命名返回值 a(这里是自己赋值给自己,a = a)
2,执行 defer:运行所有 defer 函数
3,真正返回:把 a 的值返回给调用者

执行流程

  1. a 初始为 0
  2. return a → 把 a(=0) 赋值给返回值 a(还是 0)
  3. 执行 defer → a++ → a 变成 1
  4. 函数返回 a = 1
    所以最终输出 1

总结:非命名返回值和命名返回值的区别

命名返回值让 defer 有机会修改最终返回的值;
return 会先给命名返回值赋值,再执行 defer,
所以 defer 里的 a++ 会影响到最终返回结果。

怎么区分是命名返回值和非命名返回值

括号里是 名字 类型 的形式就是:命名返回值

func f() (a int)        { ... }   // 返回 1 个,名字 a
func g() (x, y int)     { ... }   // 返回 2 个,名字 x, y
func h() (err error)    { ... }   // 名字 err

非命名返回值(只有类型):括号里只有类型,没有变量名。

func f() int            { ... }   // 只有类型
func g() (int, string)  { ... }   // 只有类型
func h() error          { ... }   // 只有类型
posted @ 2026-09-14 20:35  何人陪我共长生  阅读(9)  评论(0)    收藏  举报