首頁  >  文章  >  後端開發  >  你知道golang中的閉包的意義和用法嗎

你知道golang中的閉包的意義和用法嗎

藏色散人
藏色散人轉載
2020-12-24 15:25:222315瀏覽

下面由golang教學專欄來介紹golang中的閉包的意義和用法,希望對需要的朋友有幫助!

你知道golang中的閉包的意義和用法嗎

#什麼是閉包?

Go 函數可以是一個閉包。閉包是一個函數值,它引用了函數體之外的變數。這個函數可以對這個引用的變數進行存取和賦值;換句話說這個函數被「綁定」在這個變數上。

我的不可靠的理解,一個閉包相當於一個類別的實例,函數體之外的變數相當於這個實例儲存的變數。

沒有閉包的時候,函數就是一次性買賣,函數執行完畢後就無法再更改函數中變數的值(應該是記憶體釋放了);有了閉包後函數就變成了一個變數的值,只要變數沒被釋放,函數就會一直處於存活並獨享的狀態,因此可以後期更改函數中變數的值(因為這樣就不會被go給回收記憶體了,會一直快取在那裡)。

閉包的主要意義

縮小變數作用域,減少對全域變數的污染。下面的累加如果用全域變數進行實現,全域變數容易被其他人污染。同時,所有我要實作n個累加器,那麼每次都需要n個全域變數。利用背包,每個產生的累加器myAdder1, myAdder2 := adder(), adder()有自己獨立的sum,sum可以看作為myAdder1.sum與myAdder2.sum。

利用背包可以實現有自己狀態的函數

package mainimport (
	"fmt")func adder() func(int) int {
	sum := 0
	return func(x int) int {
		sum += x		return sum	}}func main() {
	myAdder := adder()
	
	// 从1加到10
	for i := 1; i <= 10; i++ {
		myAdder(i)
	}
	
	fmt.Println(myAdder(0))
	// 再加上45
	fmt.Println(myAdder(45))}

結果:

55		// 1+...+10
100

範例

#利用閉包實作斐波拉契數列

package mainimport (
	"fmt")func fibonacci() func() int {
	b0 := 0
	b1 := 1
	return func() int {
		tmp := b0 + b1
		b0 = b1
		b1 = tmp		return b1	}}func main() {
	myFibonacci := fibonacci()
	for i := 1; i <= 5; i++ {
		fmt.Println(myFibonacci())
	}}

結果:

1
2
3
5
8

易錯點

func B() []func() {
	b := make([]func(), 3, 3)
	for i := 0; i < 3; i++ {
		b[i] = func() {
			fmt.Println(i)
		}
	}
	return b}func main() {
	c := B()
	c[0]()
	c[1]()
	c[2]()}

結果:

// 因为都引用i,i最后变成了3
3
3
3

修正方法1:

package mainimport (
	"fmt")func B() []func() {
	b := make([]func(), 3, 3)
	for i := 0; i < 3; i++ {
		j := i
		b[i] = func() {
			fmt.Println(j)
		}
	}
	return b}func main() {
	c := B()
	c[0]()
	c[1]()
	c[2]()}

改正方法2:

package mainimport (
	"fmt")func B() []func() {
	b := make([]func(), 3, 3)
	for i := 0; i < 3; i++ {
		b[i] = func(j int) func(){
			return func() {
				fmt.Println(j)
			}
		}(i)
	}
	return b}func main() {
	c := B()
	c[0]()
	c[1]()
	c[2]()}

更多相關技術文章,請造訪go語言教學欄位!

#

以上是你知道golang中的閉包的意義和用法嗎的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:csdn.net。如有侵權,請聯絡admin@php.cn刪除