2.1.2 匿名变量和匿名函数

一、匿名变量

  1. 在编程过程中,可能会遇到没有名称的变量、类型或方法。虽然不是必须的但有时候这样做可以极大地增强代码的灵活性,这些变量统称为匿名变量

  2. 在Go语言中,匿名变量用一个下划线"_"表示,"_"本身就是一个特殊的标识符,被称为空白标识符。任何赋给这个表示赋的值都将被抛弃,因为这些值不能在后续的代码中使用,也不可以使用这个标识符作为变量对其他变量进行赋值或运算

    func GenIntNumbers() (int, int) {
    	return 6, 8
    }
    
    func main() {
    	a, _ := GenIntNumbers()
    	_, b := GenIntNumbers()
    	fmt.Println(a, b)
    }

    结果:

    6 8

  3. 匿名变量不占用内存,不会分配内存,也不会因为多次声明而无法使用

二、匿名函数

  1. 匿名函数是指没有名字的函数

  2. 匿名函数最大的用途之一是模拟块级作用域,避免数据污染,匿名函数的使用有如下几种场景

    1. 不带参数的匿名函数

      func f1() {
      	f := func() {
      		fmt.Println("不带参数的匿名函数~")
      	}
      	f()
      	fmt.Printf("%T\n", f) // 打印func()
      }

      结果:

      不带参数的匿名函数~
      func()
    2. 带参数的匿名函数

      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
    3. 带返回值的匿名函数

      func f3() {
      	f := func() string {
      		return "带返回值的匿名函数"
      	}
      	a := f()
      	fmt.Printf(a)
      }

      结果:

      带返回值的匿名函数
    4. 编写返回多个匿名函数的函数

      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

三、闭包

  1. 闭包是由函数和其他相关的引用环境组合而成的实体

  2. 闭包是从其主体外部引用变量的函数值

  3. 函数可以访问并分配给引用变量,从这个意义上说,函数是被”绑定“到了变量上

  4. 变量的实质是函数的嵌套,内层的函数可以使用外层函数的所有变量,及时外层函数已经执行完毕

    结果:

  5. 闭包通过引用的方式使用外部函数的变量

    结果:

    注释:

    1. f2()函数只调用了一次函数Func2(),构成一个闭包

    2. i在外部数组b中定义,所以闭包维护该变量i,arr[0]、arr[1]中的i都是比包中i引用的,因此执行i的值已经变成了2,故再调用a[0]()时的输出是2,不是0

  6. 要想解决5中的bug,案例如下:

    结果:

    注释:

    1. 该方法每次操作仅将匿名函数放入数组中,但未执行

    2. 并且已引用的变量是i,随着i的改变,匿名函数中的i也在改变,所以当执行这些函数时,他们读取的都是环境变量i最后一次的值

    3. 解决的方法就是每次复制变量i后传到匿名函数中,让闭包的环境变量不同

  7. 在Go语言中,default后的函数最后执行

    备注:

    1. 上述代码输出结果为2,即先执行r = 0,再执行r += 3

  8. 注意:匿名函数虽然可以给编程带来灵活性,但同时也容易产生bug,因此在使用过程中要多注意函数的参数问题

Last updated