Golang | 匿名函数和闭包


匿名函数

匿名函数就是一个没有名字的函数,当我们在一个函数内部重复调用一段代码, 并且这段代码不想被别的函数使用,我们就可以定义一个匿名函数,或者在一段代码需要并发的时候使用匿名函数。

例如:

    func main() {
    f := func() {
      fmt.Println("hello,world!")
    }
    // 第一次调用
    f()
    // 第二次调用
    f()
    // 第三次调用
    f()

    // 加锁
    wg := sync.WaitGroup{}
    wg.Add(100)
    // 并发打印一句话,100次
    for i := 0; i < 100; i++ {
      go func(i int) {
        fmt.Printf("循环第%d次\n",i)
        // 标记每一个协程的结束
        wg.Done()
      }(i+1)
    }
    // 等待所有协程都执行完毕才会结束程序
    wg.Wait()
  }

上面就是匿名函数的两个应用场景

闭包

闭包就是也是匿名函数的一种,它们允许调用定义在其它环境下的变量,闭包可以使当前函数捕捉到一个外部状态,一个闭包继承了函数所声明时的作用域,因此,作用域内的所有变量都被共享到了当前函数内,我们可以直接操作这个变量。闭包返回的时候,并不是单纯的返回一个函数,返回的是一个结构体,其中记录了函数返回地址和引用的环境中的变量地址。

一个简单的例子:

  func AddInt() func(i int) int{
    var num int
    return func(i int) int {
      num += i
      return num
    }
  }

  func main() {
    fn := AddInt()

    fmt.Println(fn(1))	// 1
    fmt.Println(fn(1))	// 2
    fmt.Println(fn(1))	// 3
    fmt.Println(fn(1)) 	// 4
  }

以上的小例子中,我们每一次调用fn 函数,每一次只在 addInt 中做加法,按照我们的理解应该l输出的全都是 1 ,但是现在输出的却是几次调用的和,这就说明了,在调用闭包函数的时候,当前函数可以闭包中的变量,也可以说明,闭包函数返回的 fn中,包含着函数的地址和当前环境中使用的变量地址。

看一下其它的闭包应用:

// 斐波那契数列:
func fibonacci() func() int {
	a, b := 0, 1
	return func() int {
		a , b = b , a + b
		return a
	}
}

func main() {
	f := fibonacci()
	for i := 0; i < 10; i++ {
		fmt.Println(f())
	}
	// 输出:
	// 1
	// 1
	// 2
	// 3
	// 5
	// 8
	// 13
	// 21
	// 34
	// 55
}
  // 装饰器 & 中间函数
	func wrapping(f func() string) {
    fmt.Println("do my work...")
    fmt.Println("wrapping function: ", f())
    fmt.Println("my work finished !")
  }

  func sayHello() string {
    return "Hello !"
  }

  func sayByeBye() string {
    return "Bye Bye !"
  }

  func main() {
    wrapping(sayHello)
    wrapping(sayByeBye)
  }
  /*
  输出:
  do my work...
  wrapping function:  Hello !
  my work finished !
  do my work...
  wrapping function:  Bye Bye !
  my work finished !
  */


关注公众号,随时获取最新资讯

细节决定成败!
个人愚见,如有不对,恳请斧正!