GO語言————6.9 應用閉包:將函式作為返回值
6.9 應用閉包:將函式作為返回值
在程式 function_return.go
中我們將會看到函式 Add2 和 Adder 均會返回簽名為 func(b int) int
的函式:
func Add2() (func(b int) int)
func Adder(a int) (func(b int) int)
函式 Add2 不接受任何引數,但函式 Adder 接受一個 int 型別的整數作為引數。
我們也可以將 Adder 返回的函式存到變數中(function_return.go)。
package main
import "fmt"
func main() {
// make an Add2 function, give it a name p2, and call it:
p2 := Add2()
fmt.Printf("Call Add2 for 3 gives: %v\n", p2(3))
// make a special Adder function, a gets value 2:
TwoAdder := Adder(2)
fmt.Printf("The result is: %v\n", TwoAdder(3))
}
func Add2() func(b int) int {
return func(b int) int {
return b + 2
}
}
func Adder(a int) func(b int) int {
return func(b int) int {
return a + b
}
}
輸出:
Call Add2 for 3 gives: 5
The result is: 5
下例為一個略微不同的實現(function_closure.go):
package main
import "fmt"
func main() {
var f = Adder()
fmt.Print(f(1), " - ")
fmt.Print(f(20), " - ")
fmt.Print(f(300))
}
func Adder() func(int) int {
var x int
return func(delta int) int {
x += delta
return x
}
}
函式 Adder() 現在被賦值到變數 f 中(型別為 func(int) int
)。
輸出:
1 - 21 - 321
三次呼叫函式 f 的過程中函式 Adder() 中變數 delta 的值分別為:1、20 和 300。
我們可以看到,在多次呼叫中,變數 x 的值是被保留的,即 0 + 1 = 1
,然後 1 + 20 = 21
,最後 21 + 300 = 321
:閉包函式儲存並積累其中的變數的值,不管外部函式退出與否,它都能夠繼續操作外部函式中的區域性變數。
這些區域性變數同樣可以是引數,例如之前例子中的 Adder(as int)
。
這些例子清楚地展示瞭如何在 Go 語言中使用閉包。
在閉包中使用到的變數可以是在閉包函式體內宣告的,也可以是在外部函式宣告的:
var g int
go func(i int) {
s := 0
for j := 0; j < i; j++ { s += j }
g = s
}(1000) // Passes argument 1000 to the function literal.
這樣閉包函式就能夠被應用到整個集合的元素上,並修改它們的值。然後這些變數就可以用於表示或計算全域性或平均值。
練習 6.9 不使用遞迴但使用閉包改寫第 6.6 節中的斐波那契數列程式。
練習 6.10
學習並理解以下程式的工作原理:
一個返回值為另一個函式的函式可以被稱之為工廠函式,這在您需要建立一系列相似的函式的時候非常有用:書寫一個工廠函式而不是針對每種情況都書寫一個函式。下面的函式演示瞭如何動態返回追加字尾的函式:
func MakeAddSuffix(suffix string) func(string) string {
return func(name string) string {
if !strings.HasSuffix(name, suffix) {
return name + suffix
}
return name
}
}
現在,我們可以生成如下函式:
addBmp := MakeAddSuffix(".bmp")
addJpeg := MakeAddSuffix(".jpeg")
然後呼叫它們:
addBmp("file") // returns: file.bmp
addJpeg("file") // returns: file.jpeg
可以返回其它函式的函式和接受其它函式作為引數的函式均被稱之為高階函式,是函式式語言的特點。我們已經在第 6.7 中得知函式也是一種值,因此很顯然 Go 語言具有一些函式式語言的特性。閉包在 Go 語言中非常常見,常用於 goroutine 和管道操作(詳見第 14.8-14.9 節)。在第 11.14 節的程式中,我們將會看到 Go 語言中的函式在處理混合物件時的強大能力。
相關文章
- GO語言————6.7 將函式作為引數Go函式
- 【Go語言學習】匿名函式與閉包Go函式
- go 閉包函式Go函式
- GO語言————6.2 函式引數與返回值Go函式
- Go語言Slice作為函式引數詳解Go函式
- GO語言————6.8 閉包Go
- Go 語言閉包詳解Go
- Go 語言函式Go函式
- GO語言————5.2 測試多返回值函式的錯誤Go函式
- Go 語言 -make函式Go函式
- GO語言————6.1 函式Go函式
- Go 語言 sync 包的應用詳解Go
- GO語言————6.10 使用閉包除錯Go除錯
- go語言學習-函式Go函式
- C語言 將函式(有參、無參)作為引數傳遞C語言函式
- 函式閉包函式
- 倉頡程式語言技術指南:巢狀函式、Lambda 表示式、閉包巢狀函式
- 函式 -- 就要學習 Go 語言函式Go
- GO語言————6.5 內建函式Go函式
- GO語言————6.6 遞迴函式Go遞迴函式
- 自制Monkey語言編譯器:實現函式閉包功能和為語言增加複雜資料結構編譯函式資料結構
- 用“揹包”去理解Go語言中的閉包Go
- 5.go語言函式提綱Go函式
- js函式閉包JS函式
- go語言採坑:閉包共享變數問題Go變數
- Go 函式的三種用法:方法、閉包、實參Go函式
- 【Go】Go語言學習筆記-2-函式Go筆記函式
- 回撥函式 與 函式閉包函式
- 閉包函式(匿名函式)的理解函式
- R語言kohonen包主要函式介紹R語言函式
- GO語言入門 - (六)函式和方法Go函式
- 小白學習Golang(六)Go語言函式Golang函式
- go語言入門之-函式和方法Go函式
- 函式閉包機制函式
- 理解Python函式閉包Python函式
- JS函式表示式——函式遞迴、閉包JS函式遞迴
- Go語言反射(reflect)及應用Go反射
- 函式物件、裝飾器、閉包函式函式物件