简单的 defer 也有可能写出BUG

defer 也要小心使用,带来的bug

defer 很简单,但也不免大意忘记写出BUG,下面这4种情况需要注意。

1、defer 参数是"立即求值"

go 复制代码
func main() {
    i := 1
    defer fmt.Println(i) // 函数运行最后输出i的值
    i = 2
}

输出1, 原因是defer方法的参数是实时计算

2、方法接收者拷贝

go 复制代码
type Car struct { 
  name string 
}

func (c Car) Print() { 
  fmt.Println(c.name) 
}

func main() {
    c := Car{name: "Mary"}
    defer c.Print() // 最后再调用Print输出
    c.name = "Tom"
}

输出的并不是Tom,因为即使调用方法是接收器,但它前面的值也会被立即计算,所有defer处就拷贝了c,与第1点原理一样。

3、误认为是作用域名结束执行

go 复制代码
for i := 0; i < 5000; i++ {
    f, _ := os.Open(fmt.Sprintf("file_%d.csv", i))
    defer f.Close()
}

所有 Close() 都在函数结束才执行,可能造成资源浪费或文件句柄可能被耗尽。

4、未注意defer执行顺序

go 复制代码
defer fmt.Println("A")
defer fmt.Println("B")
defer fmt.Println("C")

输出的是C、B、A,defer是一个栈,先入后出。

相关推荐
喵个咪1 天前
GoWind 拆解:全链 ID 类型体系——int64 定版与前端字符串化契约
前端·后端·go
喵个咪1 天前
GoWind CMS 拆解:发布审批——多级推进、逐级角色与全程留痕
前端·后端·go
喵个咪1 天前
GoWind Flow 拆解:一个 Go 工作流引擎与它的双模式设计器
前端·后端·go
喵个咪1 天前
GoWind CMS 拆解:搜索三板斧——高亮、联想、同义词
后端·搜索引擎·go
喵个咪1 天前
GoWind 拆解:AI Agent 编排引擎——波次并行、子图递归与人工审批
人工智能·后端·go
喵个咪1 天前
GoWind Admin 拆解:打印模板设计器——从画布到服务端 PDF 的完整打印链路
前端·后端·go
喵个咪1 天前
GoWind Admin 拆解:BI 大屏设计器——schema 即 JSON、resolver 注入与三张快照表的口径谱系
大数据·后端·go
Warson_L2 天前
高性能架构设计
python·go
我不会起名字3222 天前
Redis 从 0 到 1(三十七·收官):36 篇浓缩成 1 张知识地图 + 50 项生产 Checklist
redis·go·知识体系·checklist·收官
Mz码不住2 天前
用 Wails 写一个跨平台进程管理器
go