1. 程式人生 > 其它 >Golang | 匿名函式和閉包

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 !
  */


關注公眾號,隨時獲取最新資訊

細節決定成敗!
個人愚見,如有不對,懇請斧正!