<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                企業??AI智能體構建引擎,智能編排和調試,一鍵部署,支持知識庫和私有化部署方案 廣告
                [TOC] # 閉包 ## 簡介 **作用:縮小變量作用域,減少對全局變量的污染** 閉包又是什么?你可以想象一下,在一個函數中存在對外來標識符的引用。所謂的外來標識符,既不代表當前函數的任何參數或結果,也不是函數內部聲明的,它是直接從外邊拿過來的 ![](https://box.kancloud.cn/ac6a5657ad6e6e2edbae512c7788dea6_1342x662.png) 一個函數捕獲了和他在同一個作用域的其他常量和變量.這就意味著當閉包被調用的時候,不管在程序什么地方調用,閉包能夠使用這些常量或者變量. 它不關心這些捕獲了的變量和常量是否已經超出了作用域,所以只有閉包還在使用他,這些變量就還會存在. 在go里面,所有的匿名函數都是閉包 ~~~ func main() { a := 10 str := "mike" //匿名函數,沒有函數名字,函數定義沒有調用 f1 := func() { fmt.Println("a = ", a) fmt.Println("str = ", str) } //調用 f1() //給一個函數類型起別名 type FuncType func() //函數沒有參數沒有返回值 //聲明變量 var f2 FuncType f2 = f1 f2() //定義匿名函數,同時調用 func() { fmt.Printf("a = %d, str = %s\n", a, str) }() //后面的()代表調用此匿名函數 //帶參數的匿名函數 f3 := func(i, j int) { fmt.Printf("a = %d, str = %s\n", a, str) } f3(1, 2) //有參數有返回值 x, y := func(i, j int) (max, min int) { if i > j { max = i min = j } else { max = j min = i } return }(10, 20) fmt.Print(x, y) } ~~~ **閉包以引用的方式捕獲外部變量** ~~~ func main() { a := 10 str := "nike" func() { a = 666 str = "go" fmt.Printf("內部: a = %d, str = %s\n", a, str) }() //()代表直接調用 fmt.Printf("外部: a = %d, str =%s\n", a, str) } ~~~ 輸出 ~~~ 內部: a = 666, str = go 外部: a = 666, str =go ~~~ **閉包保存變量** ~~~ func test02() func() int { var x int //沒有初始化,值為0 return func() int { x++ return x * x } } func main() { //返回函數類型 f := test02() fmt.Println(f()) fmt.Println(f()) fmt.Println(f()) } ~~~ ## 使用 > Go 函數可以是一個閉包。閉包是一個函數值,它引用了函數體之外的變量。 這個函數可以對這個引用的變量進行訪問和賦值;換句話說這個函數被“綁定”在這個變量上。 例如,函數 adder 返回一個閉包。每個返回的閉包都被綁定到其各自的 sum 變量上。 在上面例子中(這里重新貼下代碼,和上面代碼一樣): ~~~ package main import "fmt" func adder() func(int) int { sum := 0 return func(x int) int { sum += x return sum } } func main() { pos, neg := adder(), adder() for i := 0; i < 10; i++ { fmt.Println( pos(i), neg(-2*i), ) } } ~~~ 如pos := adder()的adder()表示返回了一個閉包,并賦值給了pos,同時,這個被賦值給了pos的閉包函數被綁定在sum變量上,因此pos閉包函數里的變量sum和neg變量里的sum毫無關系。 `func adder() func(int) int`的`func(int) int`表示adder()的輸出值的類型是func(int) int這樣一個函數 沒有閉包的時候,函數就是一次性買賣,函數執行完畢后就無法再更改函數中變量的值(應該是內存釋放了);有了閉包后函數就成為了一個變量的值,只要變量沒被釋放,函數就會一直處于存活并獨享的狀態,因此可以后期更改函數中變量的值(因為這樣就不會被go給回收內存了,會一直緩存在那里)。 比如,實現一個計算功能:一個數從0開始,每次加上自己的值和當前循環次數(當前第幾次,循環從0開始,到9,共10次),然后\*2,這樣迭代10次: 沒有閉包的時候這么寫: ~~~ func abc(x int) int { return x * 2 } func main() { var a int for i := 0; i < 10; i ++ { a = abc(a+i) fmt.Println(a) } } ~~~ 如果用閉包可以這么寫: ~~~ func abc() func(int) int { res := 0 return func(x int) int { res = (res + x) * 2 return res } } func main() { a := abc() for i := 0; i < 10; i++ { fmt.Println(a(i)) } } ~~~ 2種寫法輸出值都是: ~~~ 0 2 8 22 52 114 240 494 1004 2026 ~~~ 從上面例子可以看出閉包的3個好處: 1. 不是一次性消費,被引用聲明后可以重復調用,同時變量又只限定在函數里,同時每次調用不是從初始值開始(函數里長期存儲變量) 這有點像使用面向對象的感覺,實例化一個類,這樣這個類里的所有方法、屬性都是為某個人私有獨享的。但比面向對象更加的輕量化 2. 用了閉包后,主函數就變得簡單了,把算法封裝在一個函數里,使得主函數省略了a=abc(a+i)這種麻煩事了 3. 變量污染少,因為如果沒用閉包,就會為了傳遞值到函數里,而在函數外部聲明變量,但這樣聲明的變量又會被下面的其他函數或代碼誤改。 關于閉包的第一個好處,再啰嗦舉個例子 1. 若不用閉包,則容易對函數外的變量誤操作(誤操作別人),例: ~~~ var A int = 1 func main() { foo := func () { A := 2 fmt.Println(A) } foo() fmt.Println(A) } ~~~ 輸出: ~~~ 2 1 ~~~ 如果手誤將A := 2寫成了A = 2,那么輸出就是: ~~~ 2 2 ~~~ 即會影響外部變量A 2. 為了將某一個私有的值傳遞到某個函數里,就需要在函數外聲明這個值,但是這樣聲明會導致這個值在其他函數里也可見了(別人誤操作我),例: ~~~ func main() { A := 1 foo := func () int { return A + 1 } B := 1 bar := func () int { return B + 2 } fmt.Println(foo()) fmt.Println(bar()) } ~~~ 輸出: ~~~ 2 3 ~~~ 在bar里是可以對變量A做操作的,一個不小心就容易誤修改變量A **結論:函數外的變量只能通過參數傳遞進去,不要通過全局變量的方式的渠道傳遞進去,當函數內能讀取到的變量越多,出錯概率(誤操作)也就越高。**
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看