package main import "fmt" func main() { fmt.Println("main()开始执行") defer func() { fmt.Println("这是第1个defer") }() defer func() { fmt.Println("这是第2个defer") }() defer func() { fmt.Println("这是第3个defer") }() fmt.Println("main()执行完毕") } // ========== 输出过程·开始 ========== // // main()开始执行 // main()执行完毕 // 这是第3个defer // 这是第2个defer // 这是第1个defer // ========== 输出过程·结束 ========== // // ========== 总结 ========== // // 1、函数体中如果设置了多个defer,那么后设置的会先执行。
package main import "fmt" func main() { slice := []int{1001, 1002} // 长度为2的int切片 array := [2]int{2001, 2002} // 长度为2的int数组 defer func(s []int) { fmt.Printf("slice:%d %d \n", s[0], s[1]) // slice:1003 1004 }(slice) defer func(a [2]int) { fmt.Printf("array:%d %d \n", a[0], a[1]) // array:2001 2002 }(array) slice[0] = 1003 slice[1] = 1004 array[0] = 2003 array[1] = 2004 fmt.Println("即将执行defer操作……") } // ========== 输出过程·开始 ========== // // 即将执行defer操作…… // array:2001 2002 // slice:1003 1004 // ========== 输出过程·结束 ========== // // ========== 总结 ========== // // 1、如果defer后面调用的匿名函数传入参数,那么形参的值恒定为设置defer那一刻的值,后续修改实参不会再影响形参。 // 以上面的array变量为例,虽然在设置defer之后又修改了array变量,但设置defer时形参a的值已经固定为{2001, 2002}了, // 后续不管怎么修改array变量都不会再影响形参a的值。 // 2、defer后面调用的匿名函数传入切片变量似乎违背了上面的结论,其实不然,因为切片的数据结构里有指针(可查看源码), // 程序是通过指针去访问切片元素的,所以匿名函数打印出来的是slice变量修改后的内容,这并没有和上面的结论冲突。 // 数据结构无指针:基本数据类型(int|float|bool|string)、数组、结构体(struct) // 数据结构有指针:map、chan、切片(slice)、接口(interface)、函数(func)、指针
Copyright © 2024 码农人生. All Rights Reserved