2.1.2 匿名变量和匿名函数
一、匿名变量
在编程过程中,可能会遇到没有名称的变量、类型或方法。虽然不是必须的但有时候这样做可以极大地增强代码的灵活性,这些变量统称为匿名变量
在Go语言中,匿名变量用一个下划线
"_"表示,"_"本身就是一个特殊的标识符,被称为空白标识符。任何赋给这个表示赋的值都将被抛弃,因为这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其他变量进行赋值或运算func GenIntNumbers() (int, int) { return 6, 8 } func main() { a, _ := GenIntNumbers() _, b := GenIntNumbers() fmt.Println(a, b) }结果:
6 8
匿名变量不占用内存,不会分配内存,也不会因为多次声明而无法使用
二、匿名函数
匿名函数是指没有名字的函数
匿名函数最大的用途之一是模拟块级作用域,避免数据污染,匿名函数的使用有如下几种场景
不带参数的匿名函数
func f1() { f := func() { fmt.Println("不带参数的匿名函数~") } f() fmt.Printf("%T\n", f) // 打印func() }结果:
不带参数的匿名函数~ func()带参数的匿名函数
func f2() { f := func(args string) { fmt.Println(args) } f("带参数的匿名函数~写法1") // 或 (func(args string) { fmt.Println(args) })("带参数的匿名函数~写法2") // 或 func(args string) { fmt.Println(args) }("带参数的匿名函数~写法3") }结果:
带参数的匿名函数~写法1 带参数的匿名函数~写法2 带参数的匿名函数~写法3带返回值的匿名函数
func f3() { f := func() string { return "带返回值的匿名函数" } a := f() fmt.Printf(a) }结果:
带返回值的匿名函数编写返回多个匿名函数的函数
func f4() { f1, f2 := MultiFunc(6, 8) fmt.Println(f1(1)) // 7 fmt.Println(f2()) // 28 } func MultiFunc(a, b int) (func(int) int, func() int) { f1 := func(c int) int { return (a + b) * c / 2 } f2 := func() int { return 2 * (a + b) } return f1, f2 }结果:
7 28
三、闭包
闭包是由函数和其他相关的引用环境组合而成的实体
闭包是从其主体外部引用变量的函数值
函数可以访问并分配给引用变量,从这个意义上说,函数是被”绑定“到了变量上
变量的实质是函数的嵌套,内层的函数可以使用外层函数的所有变量,及时外层函数已经执行完毕
结果:
闭包通过引用的方式使用外部函数的变量
结果:
注释:
f2()函数只调用了一次函数Func2(),构成一个闭包i在外部数组b中定义,所以闭包维护该变量i,arr[0]、arr[1]中的i都是比包中i引用的,因此执行i的值已经变成了2,故再调用
a[0]()时的输出是2,不是0
要想解决5中的bug,案例如下:
结果:
注释:
该方法每次操作仅将匿名函数放入数组中,但未执行
并且已引用的变量是i,随着i的改变,匿名函数中的i也在改变,所以当执行这些函数时,他们读取的都是环境变量i最后一次的值
解决的方法就是每次复制变量i后传到匿名函数中,让闭包的环境变量不同
在Go语言中,default后的函数最后执行
备注:
上述代码输出结果为2,即先执行r = 0,再执行r += 3
注意:匿名函数虽然可以给编程带来灵活性,但同时也容易产生bug,因此在使用过程中要多注意函数的参数问题
Last updated