1.匿名函數和閉包的概念
匿名函數: 聲明函數時不顯式聲明函數名。
閉包: 簡單來說就是一個函數定義中引用了函數外定義的變量,並且該函數可以在其定義環境外被執行。這樣的一個函數我們稱之爲閉包。實際上閉包可以看做一種更加廣義的函數概念。因爲其已經不再是傳統意義上定義的函數。
go語言中的匿名函數聲明方法類似於js,而閉包聲明類似於python。
demo:
package main
import "fmt"
func main() {
a := 10
str := "golang"
//匿名函數,沒有函數名字
//可以捕獲同一個作用域的變量
f1 := func() {
fmt.Println(a, str)
}
f1()
//給一個函數類型起別名
type FuncType func() //函數沒有參數,沒有返回值
// 聲明變量
var f2 FuncType
f2 = f1
f2()
// 定義匿名函數的同時調用
func() {
fmt.Println(a, str)
}() // 後面的()代表調用此匿名函數
// 帶參數的匿名函數
func(i, j int) {
fmt.Println(i + j)
}(5, 6)
// 匿名函數有參有返回值
var b = func(i, j int) int {
return i + j
}(5, 7)
fmt.Println(b)
func() {
//閉包以引用的方式捕獲外部變量,裏面改了外面的變量也會被改變
a = 66
str = "abc"
fmt.Println("內部:", a, str)
}()
fmt.Println("外部: ", a, str)
}
2.閉包的特點
- 閉包不關心這些捕獲了的變量和常量是否已經超出了作用域,只要閉包還在使用這些變量,那麼這些變量就不會被垃圾回收
- 我們看到的變量的生命週期不由它的作用域決定,當f返回後,變量x仍然隱式的存在於f中。
package main
import "fmt"
// 返回一個匿名函數
func test() func() int {
var x int
return func() int { //閉包
x++
return x * x
}
}
//閉包不關心這些捕獲了的變量和常量是否已經超出了作用域,只要閉包還在使用這些變量,那麼這些變量就不會被垃圾回收
//我們看到的變量的生命週期不由它的作用域決定,當f返回後,變量x仍然隱式的存在於f中。
func main() {
var f = test()
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
fmt.Println(f())
}