defer测试
package main
import (
"fmt"
"sync"
"testing"
)
//调用顺序
//最早调用的defer会在最后执行
func test0() {
defer func() {
fmt.Print("a\n")
}()
defer func() {
fmt.Print("b")
}()
defer func() {
fmt.Print("c")
}()
fmt.Println("test 0")
}
//defer是在函数结束后返回前被执行
//并且lambda闭包传的是值的引用
//也就是说如果返回值在函数定义时被命名,在defer调用的函数中就可以修改返回值
func test1() {
doubleSum := func(x, y int) (z int) { //don't forget add () with return expression
fmt.Printf("start:x(%p)=%d,y(%p)=%d,z(%p)=%d\n", &x, x, &y, y, &z, z)
defer func() {
fmt.Printf("defer:x(%p)=%d,y(%p)=%d,z(%p)=%d\n", &x, x, &y, y, &z, z)
z = z * 2
}()
x = x * 2
y = y * 2
return x + y
}
fmt.Println("test 1")
x, y := 10, 20
z := doubleSum(x, y)
fmt.Printf("x=%d,y=%d,z=%d\n", x, y, z)
}
// defer是在调用时传参,而不是在执行时传参
func test2() {
otherDoubleSum := func(x, y int) (z int) { //don't forget add () with return expression
defer func(ret int) {
fmt.Printf("defer:x=%d,y=%d,z=%d\n", x, y, ret)
ret = ret
}(z) // 这个时候z的值是0而不是x+y
x = x * 2
y = y * 2
return x + y
}
fmt.Println("test 2")
x, y := 10, 20
z := otherDoubleSum(10, 20)
fmt.Printf("x=%d,y=%d,z=%d\n", x, y, z)
}
// 可以在defer的函数中捕获panic
func test3() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("panic: %s\n", err)
}
}()
fmt.Println("test 3")
panic("panic test!")
}
// 延迟调用中引发的错误,可被后续延迟调用捕获, 但仅仅最后一个panic会被捕获
func test4() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("recover: %s\n", err)
}
}()
defer func() {
panic("defer panic")
}()
fmt.Println("test 4")
panic("panic test!")
}
// defer的性能测试,开销不小
var lock sync.Mutex
func TestLock() {
lock.Lock()
lock.Unlock()
}
func TestDeferLock() {
lock.Lock()
defer lock.Unlock()
}
func BenchmarkTest(b *testing.B) {
for i := 0; i < b.N; i++ {
TestLock()
}
}
func BenchmarkTestDefer(b *testing.B) {
for i := 0; i < b.N; i++ {
TestDeferLock()
}
}
func main() {
test0()
test1()
test2()
test3()
test4()
// 性能测试跑的时间太长无法在play中
// fmt.Println(testing.Benchmark(BenchmarkTest))
// fmt.Println(testing.Benchmark(BenchmarkTestDefer))
}