GO語言————6.8 閉包
6.8 閉包
當我們不希望給函式起名字的時候,可以使用匿名函式,例如:func(x, y int) int { return x + y }
。
這樣的一個函式不能夠獨立存在(編譯器會返回錯誤:non-declaration statement outside function body
),但可以被賦值於某個變數,即儲存函式的地址到變數中:fplus := func(x, y int) int { return x + y }
,然後通過變數名對函式進行呼叫:fplus(3,4)
。
當然,您也可以直接對匿名函式進行呼叫:func(x, y int) int { return x + y } (3, 4)
。
下面是一個計算從 1 到 1 百萬整數的總和的匿名函式:
func() {
sum := 0
for i := 1; i <= 1e6; i++ {
sum += i
}
}()
表示引數列表的第一對括號必須緊挨著關鍵字 func
,因為匿名函式沒有名稱。花括號 {}
涵蓋著函式體,最後的一對括號表示對該匿名函式的呼叫。
下面的例子展示瞭如何將匿名函式賦值給變數並對其進行呼叫(function_literal.go):
package main
import "fmt"
func main() {
f()
}
func f() {
for i := 0; i < 4; i++ {
g := func(i int) { fmt.Printf("%d ", i) } //此例子中只是為了演示匿名函式可分配不同的記憶體地址,在現實開發中,不應該把該部分資訊放置到迴圈中。
g(i)
fmt.Printf(" - g is of type %T and has value %v\n", g, g)
}
}
輸出:
0 - g is of type func(int) and has value 0x681a80
1 - g is of type func(int) and has value 0x681b00
2 - g is of type func(int) and has value 0x681ac0
3 - g is of type func(int) and has value 0x681400
我們可以看到變數 g
代表的是 func(int)
,變數的值是一個記憶體地址。
所以我們實際上擁有的是一個函式值:匿名函式可以被賦值給變數並作為值使用。
練習 6.8 在 main 函式中寫一個用於列印 Hello World
字串的匿名函式並賦值給變數 fv
,然後呼叫該函式並列印變數 fv
的型別。
匿名函式像所有函式一樣可以接受或不接受引數。下面的例子展示瞭如何傳遞引數到匿名函式中:
func (u string) {
fmt.Println(u)
…
}(v)
請學習以下示例並思考(return_defer.go):函式 f
返回時,變數 ret
的值是什麼?
package main
import "fmt"
func f() (ret int) {
defer func() {
ret++
}()
return 1
}
func main() {
fmt.Println(f())
}
變數 ret
的值為 2,因為 ret++
是在執行 return 1
語句後發生的。
這可用於在返回語句之後修改返回的 error
時使用。
defer 語句和匿名函式
關鍵字 defer
(詳見第 6.4 節)經常配合匿名函式使用,它可以用於改變函式的命名返回值。
匿名函式還可以配合 go
關鍵字來作為 goroutine 使用(詳見第 14 章和第 16.9 節)。
匿名函式同樣被稱之為閉包(函式式語言的術語):它們被允許呼叫定義在其它環境下的變數。閉包可使得某個函式捕捉到一些外部狀態,例如:函式被建立時的狀態。另一種表示方式為:一個閉包繼承了函式所宣告時的作用域。這種狀態(作用域內的變數)都被共享到閉包的環境中,因此這些變數可以在閉包中被操作,直到被銷燬,詳見第 6.9 節中的示例。閉包經常被用作包裝函式:它們會預先定義好 1 個或多個引數以用於包裝,詳見下一節中的示例。另一個不錯的應用就是使用閉包來完成更加簡潔的錯誤檢查(詳見第 16.10.2 節)。
相關文章
- Go 語言閉包詳解Go
- GO語言————6.10 使用閉包除錯Go除錯
- 【Go語言學習】匿名函式與閉包Go函式
- go語言採坑:閉包共享變數問題Go變數
- [06 Go語言基礎-包]Go
- 用“揹包”去理解Go語言中的閉包Go
- go語言處理TCP拆包/粘包GoTCP
- go 學習筆記之10 分鐘簡要理解 go 語言閉包技術Go筆記
- GO語言————6.9 應用閉包:將函式作為返回值Go函式
- Go 語言操作 MySQL 之 SQLX 包GoMySql
- Go 語言 context 包實踐GoContext
- 【Go】Go語言學習筆記-3-包Go筆記
- Go語言基於go module方式管理包(package)GoPackage
- 2-2 Go語言的包(package)GoPackage
- go 閉包函式Go函式
- Go | 閉包的使用Go
- Go 語言 sync 包的應用詳解Go
- GO語言————4.7 strings和strconv 包Go
- GO語言手動處理TCP粘包GoTCP
- Go語言Context包原始碼學習GoContext原始碼
- Go語言————1、初識GO語言Go
- Go 閉包的實現Go
- 聊聊Go裡面的閉包Go
- [ gev ] Go 語言優雅處理 TCP “粘包”GoTCP
- go語言reflect包使用的幾個場景Go
- GO語言Go
- Swift 1.1語言第7章 函式和閉包Swift函式
- GO語言————2、GO語言環境安裝Go
- go 閉包學習筆記Go筆記
- Go知識盲區--閉包Go
- go 閉包捕獲問題Go
- 《Go 語言程式設計》 讀書筆記 (八) 包Go程式設計筆記
- 如何設計一門語言(七)——閉包、lambda和interface
- Go_go語言初探Go
- 【Go語言入門系列】(八)Go語言是不是面嚮物件語言?Go物件
- go 語言常量Go
- Go語言mapGo
- go 語言切片Go