使用Defer的几个场景
Go 语言中的 也正因为 Go 语言遵循的是正交的设计,所以才有了: "少是指数级的多/Less is exponentially more" 的说法. 因为是正交的设计,最终得到的组合形式是指数级的组合形式. 相反,C++的特性虽然很多,但是很多不是正交的设计,而只是简单的特性罗列,所以C++的很多地方是无法达到指数级的多的组合方式的. 但是学习成本却非常高. 简单的例子就是C++的构造函数和析构函数和C语言的函数和 关于 Go 语言中 C++ 中模拟的 这里主要是总结 1. 简化资源的回收 这是最常见的 mu.Lock() defer mu.Unlock() 当然, mu.Lock() count++ mu.Unlock() 从简化资源的释放角度看, 2.
Go语言中, 比如: func main() { f() fmt.Println("Returned normally from f.") } func f() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f",r) } }() fmt.Println("Calling g.") g() fmt.Println("Returned normally from g.") } func g() { panic("ERROR") } 因此,如果要捕获Go语言中函数的异常,就离不开 3. 修改返回值
比如: func doubleSum(a,b int) (sum int) { defer func() { sum *= 2 }() sum = a + b } 当然,这个特性应该只是 4. 安全的回收资源 前面第一点提到, 其实,也不完全是这样,特别是在涉及到第二点提到的 比如,有一个线程安全的slice修改函数,为了性能没有使用 func set(mu *sync.Mutex,arr []int,i,v int) { mu.Lock() arr[i] = v mu.Unlock() } 但是,如果 如果用 func set(mu *sync.Mutex,v int) { mu.Lock() defer mu.Unlock() arr[i] = v } 当然,Go语言约定异常不会跨越 不过对于一些比较特殊的 比如有以下的测试函数(详情请参考Issue5746): func TestFailed(t *testing.T) { var wg sync.WaitGroup for i := 0; i < 2; i++ { wg.Add(1) go func(id int) { // defer wg.Done() t.Fatalf("TestFailed: id = %vn",id) wg.Done() }(i) } wg.Wait() } 当测试失败的时候, 对于这个例子,安全的做法是使用 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |