1. 程式人生 > GO語言入門 >24 Go 語言中的閉包

24 Go 語言中的閉包

本文主要介紹 Go 語言中的閉包。簡單的說 Go 語言的閉包就是一個引用了外部自由變數匿名函式,被引用的自由變數和該匿名函式共同存在,不會因為離開了外部環境就被釋放或者刪除,還可以在這個匿名函式中繼續使用。

1. Go 語言的匿名函式

在上文中我們瞭解到了一個新的詞彙——匿名函式,我們先來學習一下Go語言中的匿名函式,再來了解在 Go 語言中如何使用閉包。匿名函式,顧名思義,就是隱藏函式名的函式。

程式碼示例

package main

import (
    "fmt"
)

var f = func() {
    fmt.Println("匿名函式作為變數來使用")
}

func
main() { f() func() { fmt.Println("匿名函式直接使用") }() }
  • 第7~9行:定義一個函式型別,值為一個匿名函式的變數;
  • 第 12 行:使用這個匿名函式;
  • 第 14~16 行:定義一個匿名函式。在這個函式後加上(),就可以直接使用這個匿名函式。

執行結果

圖片描述

2. 匿名函式引用外部變數

如果在匿名函式內,使用了外部環境的變數,就構成了一個閉包。簡單來講就是一個函式內,使用匿名函式來操作函式內宣告的變數。

程式碼示例

package main

import (
    "fmt"
)

func main
() { str := "Hello World!" func() { str = "Hello Codey!" }() fmt.Println(str) }
  • 第 10 行:匿名函式直接操作了main函式之中的變數str,將其修改為了"Hello Codey!";
  • 第 12 行:輸出變數的值。

執行結果

圖片描述

上述例子簡單的構造了一個閉包,在匿名函式中並沒有宣告或者定義str這個變數,但是可以直接操作,就是引用可main函式中的自由變數。這個例子可能對自由變數的引用表現不是很直觀,我們接下來使用defer和閉包相結合,深入瞭解一下閉包中的引用外部變數。

程式碼示例

package main

import (
    "fmt"
)

func main() {
    str := "Hello World!"
    defer func() {
        fmt.Println("defer str=", str)
    }()
    str = "Hello Codey!"
    fmt.Println("main str=", str)
}

執行結果

圖片描述

從執行結果上來看應該是蠻出人意料的,因為前文介紹 defer 的時候明確介紹了 defer 後變數是保留它在 defer 時的值,而不會被 defer 之後的程式碼所改變。但是在閉包這邊這個看起來不太適用,其實是適用的,只是閉包是引用了這個變數,也就是說,在 defer 時被保留下來的是這個變數的地址,後續程式碼改變的不是地址,而是這個地址儲存的值,所以後續程式碼對這個變數的操作,都會反應到這個 defer 中。

Tips:關於變數的地址,在後續的Go語言的指標中會有詳細的介紹。

3. 小結

本文主要介紹了 Go 語言中閉包的使用,需要注意以下幾點:

  • 閉包就是匿名函式引用外部變數
  • 閉包中引用的變數會被外部環境改變,同時閉包內對變數的改變也會影響到外部環境的使