Golang閉包

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

wKioL1YfWKXxKfnzAABdlluUiKs571.jpg

// 工廠函數,返回值也是一個函數
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))
}

wKiom1YfWLfSefPmAABr7vP0oT4056.jpg

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

wKioL1YfWpyhwQw6AAGAfOsAGpQ888.jpg

    首先強調一點,x是閉包中被捕獲的變量,y只是閉包內部的局部變量,而非被捕獲的變量。所以,對於每一次引用,x的地址都是固定的,是同一個引用變量;y的地址則是變化的。另外,閉包被引用了兩次,由此產生了兩個閉包實例,即addNum := addNumber(5)addNum1 :=addNumber(5)是兩個不一樣實例,其中引用的兩個x變量也來自兩個不一樣的實例。

相關文章
相關標籤/搜索