defer/panic

defer

1.defer语句后面必须是函数调用,不能是语句,例如:

func hello() {
    fmt.Println("hello")
}
func getString() string {
    defer func(x int) {
        fmt.Println(x)
    }(1)
    defer hello()
    return "abd"
}

2.defer语句执行的函数在本函数执行完毕后执行
3.每次defer语句执行的时候,会把函数“压栈”,函数参数会被拷贝下来,在return前会按照出栈顺序执行这些函数,而执行这些函数的参数值可以是defer时的值,也可以是执行函数时的值,这主要看defer的是一个闭包还是一个函参传递,如果是函参传递,则值确定好了,如果是一个闭包则使用外部值,即最后确定的外部值。
4.defer函数执行的顺序:
1. 先给返回值赋值
2. 执行defer语句
3. 包裹函数return返回
举例:

func f1() int { //匿名返回值
    var r int = 6
    defer func() {
            r *= 7
    }()
    return r
} //这里返回6,先复制r = 6然后执行defer语句
func f2() (r int) { //有名返回值
    defer func() {
        r *= 7
    }()
    return 6
}//这里返回42 
func f3() (r int) { //有名返回值
    defer func(r int) {
        r *= 7
    }(r)
    return 6
}//这里返回6

f1的结果是6。f1是匿名返回值,匿名返回值是在return执行时被声明,因此defer声明时,还不能访问到匿名返回值,defer的修改不会影响到返回值。
f2先给返回值r赋值,r=6,执行defer语句,defer修改r, r = 42,然后函数return。
f3是有名返回值,但是因为r是作为defer的传参,在声明defer的时候,就进行参数拷贝传递,所以defer只会对defer函数的局部参数有影响,不会影响到调用函数的返回值。

panic

1.panic不仅可以传入string,也可以传入别的类型,例如

panic("panic!!!") //输出panic: panic!!!
panic([]int{1, 2}) //输出panic: ([]int) (0x49be80,0xc0000b6000)
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容