一 、定義:
閉包:要有一個需要保護的局部變量+一個匿名函數
二、閉包的兩種寫法:
1. 在主函數之外定義一個閉包函數,閉包函數的格式爲:
func 函數名 func() int{
res = func() int{
......
}
return res
}
舉例一:
package main import "fmt" func main() { //主函數始終存在對add2的引用,因此只要主函數沒被關閉,gc就不會回收add2中的s res := add2() //此時,res的實質是函數 res = func(int)int fmt.Printf("res = %T", res) for i := 0; i < 10;i++ { fmt.Printf("i=%d ", i) sum := res(i) //res既然是個函數,那麼傳入對應的參數即可。 fmt.Println(sum) } } func add2() func(int)int{ s := 0 res := func(i int) int{ s += i return s } return res }
舉例二:
package main import "fmt" func main() { res := counter() //先看看res的類型 fmt.Printf("%T \n", res) //func() int //再看看res的值 fmt.Printf("res=%d \n", res) //res=4771872 //最後看看res()的值 fmt.Printf("res()=%d \n",res()) //res()=1 注意思考這裏爲什麼是1 fmt.Println("res():", res()) //res()=2 注意思考這裏爲什麼是2 fmt.Println("res():", res())//res()=3 注意思考這裏爲什麼是3 fmt.Println("res():", res())//res()=4 注意思考這裏爲什麼是4 //現在再賦給一個變量res2,注意觀察它的內存地址與值 fmt.Printf("res=%d \n", res) //res=4771872 //最後看看res()的值 fmt.Printf("res()=%d \n",res()) //res()=5 注意思考這裏爲什麼是1 fmt.Println("res():", res()) //res()=6 注意思考這裏爲什麼是2 res2 := counter() fmt.Printf("res2:",res2) //4774192 fmt.Println("res2():" , res2()) fmt.Println("res2():" , res2()) fmt.Println("res2():" , res2()) } //用閉包實現counter功能,並注意觀察各類類型 //閉包的步驟:1. 在函數中寫一個匿名函數“func() 返回值類型{}”,並用一個變量接受 // 2. 返回匿名函數 // 3. 在主方法中用變量接收函數counter.其實也就是接收閉包函數 func counter() func() int{ i := 0 res := func() int{ i += 1 return i } //注意觀察這裏的res其實是個地址 fmt.Printf("Counter中的res=%d \n" , res) //Counter中的res=4771872 return res }
2. 閉包的另一種省略寫法:
直接在主函數中定義一個閉包:
res := func() (func() int){
return func() int{
}
}()
舉例一:
package main import "fmt" func main() { /** 閉包另一種省略寫法 1. 定義一個匿名閉包函數,這個閉包函數是沒有參數的,但一定有返回值,返回一個匿名函數 2. 定義內部的匿名函數,內部的匿名函數一定要與返回的匿名函數類型一致 3. 返回剛剛定義的匿名函數 4. 匿名函數的用法:在聲明的時候就調用必須在後面加上() 綜上所述,閉包寫法爲: res := func() (func() int){ }() */ res := func () (func() int){ i := 10 return func() int{ i++ return i } }() fmt.Println(res) //這樣輸出來的是地址 fmt.Println(res()) //res()代表運行閉包中的函數 }