1. 程式人生 > >Go入門自學寶典0012-匿名函式與閉包

Go入門自學寶典0012-匿名函式與閉包

匿名函式與閉包
所謂閉包就是一個函式“捕獲”了和它在同一作用域的其它常量和變數。這就意味著當閉包被呼叫的時候,不管在程式什麼地方呼叫,閉包能夠使用這些常量或者變數。它不關心這些捕獲了的變數和常量是否已經超出了作用域,所以只有閉包還在使用它,這些變數就還會存在。

在Go語言裡,所有的匿名函式(Go語言規範中稱之為函式字面量)都是閉包。匿名函式是指不需要定義函式名的一種函式實現方式,它並不是一個新概念,最早可以回溯到1958年的Lisp語言。

func main() {
i := 0
str := “mike”

//方式1
f1 := func() { //匿名函式,無參無返回值
    //引用到函式外的變數
    fmt.Printf("方式1:i = %d, str = %s\n", i, str)
}

f1() //函式呼叫

//方式1的另一種方式
type FuncType func() //宣告函式型別, 無參無返回值
var f2 FuncType = f1
f2() //函式呼叫

//方式2
var f3 FuncType = func() {
    fmt.Printf("方式2:i = %d, str = %s\n", i, str)
}
f3() //函式呼叫

//方式3
func() { //匿名函式,無參無返回值
    fmt.Printf("方式3:i = %d, str = %s\n", i, str)
}() //別忘了後面的(), ()的作用是,此處直接呼叫此匿名函式

//方式4, 匿名函式,有參有返回值
v := func(a, b int) (result int) {
    result = a + b
    return
}(1, 1) //別忘了後面的(1, 1), (1, 1)的作用是,此處直接呼叫此匿名函式, 並傳參
fmt.Println("v = ", v)

}

閉包捕獲外部變數特點:
func main() {
i := 10
str := “mike”
func() {
i = 100
str = “go”
//內部:i = 100, str = go
fmt.Printf(“內部:i = %d, str = %s\n”, i, str)
}() //別忘了後面的(), ()的作用是,此處直接呼叫此匿名函式

//外部:i = 100, str = go
fmt.Printf("外部:i = %d, str = %s\n", i, str)

}

函式返回值為匿名函式:
// squares返回一個匿名函式,func() int
// 該匿名函式每次被呼叫時都會返回下一個數的平方。
func squares() func() int {
var x int
return func() int {//匿名函式
x++ //捕獲外部變數
return x * x
}
}

func main() {
f := squares()
fmt.Println(f()) // “1”
fmt.Println(f()) // “4”
fmt.Println(f()) // “9”
fmt.Println(f()) // “16”
}

函式squares返回另一個型別為 func() int 的函式。對squares的一次呼叫會生成一個區域性變數x並返回一個匿名函式。每次呼叫時匿名函式時,該函式都會先使x的值加1,再返回x的平方。第二次呼叫squares時,會生成第二個x變數,並返回一個新的匿名函式。新匿名函式操作的是第二個x變數。

通過這個例子,我們看到變數的生命週期不由它的作用域決定:squares返回後,變數x仍然隱式的存在於f中。