1 形式含義數組
所謂閉包就是一個函數「捕獲」了和它在同一做用於的其餘常量和變量。閉包
從形式上看,在Golang中,全部的匿名函數都是閉包。閉包的建立方式和普通函數幾乎一致,只有一個關鍵區別:閉包沒有名字。ide
咱們來看兩個例子函數
addPng := func(name string) string { return name + ".png" } addJpg := func(name string) string { return name + ".jpg" } filename := "abc" fmt.Println(addPng(filename), addJpg(filename))
結果以下spa
// 工廠函數,返回值也是一個函數 funcaddSuffix(suffix string) func(string) string { return func(name string) string { if !strings.HasSuffix(name, suffix) { name = name + suffix } return name } } … func main() { … addZip := addSuffix(".zip") addTgz := addSuffix(".tar.gz") fmt.Println(addZip(filename),addTgz(filename)) }
2 實質含義blog
僅僅從形式上將閉包簡單理解爲匿名函數是不夠的,還須要理解閉包實質上的含義。ip
實質上看,閉包是由函數及其相關引用環境組合而成的實體(即:閉包=函數+引用環境)。閉包在運行時能夠有多個實例,不一樣的引用環境和相同的函數組合能夠產生不一樣的實例。由閉包的實質含義,咱們能夠推論:閉包獲取捕獲變量至關於引用傳遞,而非值傳遞;對於閉包函數捕獲的常量和變量,不管閉包什麼時候何處被調用,閉包均可以使用這些常量和變量,而不用關心它們表面上的做用域。作用域
咱們用一個例子來進行驗證。
get
funcaddNumber(x int) func(int) { fmt.Printf("x: %d, addr of x:%p\n", x, &x) return func(y int) { k := x + y x = k y = k fmt.Printf("x: %d, addr of x:%p\n", x, &x) fmt.Printf("y: %d, addr of y:%p\n", y, &y) } } func main() { addNum := addNumber(5) addNum(1) addNum(1) addNum(1) fmt.Println("---------------------") addNum1 := addNumber(5) addNum1(1) addNum1(1) addNum1(1) }
運行結果
string
首先強調一點,x是閉包中被捕獲的變量,y只是閉包內部的局部變量,而非被捕獲的變量。所以,對於每一次引用,x的地址都是固定的,是同一個引用變量;y的地址則是變化的。另外,閉包被引用了兩次,由此產生了兩個閉包實例,即addNum := addNumber(5)和addNum1 :=addNumber(5)是兩個不一樣實例,其中引用的兩個x變量也來自兩個不一樣的實例。