久久久久久久视色,久久电影免费精品,中文亚洲欧美乱码在线观看,在线免费播放AV片

<center id="vfaef"><input id="vfaef"><table id="vfaef"></table></input></center>

    <p id="vfaef"><kbd id="vfaef"></kbd></p>

    
    
    <pre id="vfaef"><u id="vfaef"></u></pre>

      <thead id="vfaef"><input id="vfaef"></input></thead>

    1. 站長(zhǎng)資訊網(wǎng)
      最全最豐富的資訊網(wǎng)站

      在Go中什么是defer?怎么用?

      本文由go語(yǔ)言教程欄目給大家介紹,主題是關(guān)于go defer的學(xué)習(xí)使用,希望對(duì)需要的朋友有所幫助!

      什么是defer?

      在Go中,一個(gè)函數(shù)調(diào)用可以跟在一個(gè)defer關(guān)鍵字后面,形成一個(gè)延遲函數(shù)調(diào)用。
      當(dāng)一個(gè)函數(shù)調(diào)用被延遲后,它不會(huì)立即被執(zhí)行。它將被推入由當(dāng)前協(xié)程維護(hù)的一個(gè)延遲調(diào)用堆棧。 當(dāng)一個(gè)函數(shù)調(diào)用(可能是也可能不是一個(gè)延遲調(diào)用)返回并進(jìn)入它的退出階段后,所有在此函數(shù)調(diào)用中已經(jīng)被推入的延遲調(diào)用將被按照它們被推入堆棧的順序逆序執(zhí)行。 當(dāng)所有這些延遲調(diào)用執(zhí)行完畢后,此函數(shù)調(diào)用也就真正退出了。
      舉個(gè)簡(jiǎn)單的例子:

      package mainimport "fmt"func sum(a, b int) {     defer fmt.Println("sum函數(shù)即將返回")     defer fmt.Println("sum函數(shù)finished")     fmt.Printf("參數(shù)a=%v,參數(shù)b=%v,兩數(shù)之和為%vn", a, b, a+b)}func main() {     sum(1, 2)}

      output:

      參數(shù)a=1,參數(shù)b=2,兩數(shù)之和為3 sum函數(shù)finished sum函數(shù)即將返回

      事實(shí)上,每個(gè)協(xié)程維護(hù)著兩個(gè)調(diào)用堆棧。

      • 一個(gè)是正常的函數(shù)調(diào)用堆棧。在此堆棧中,相鄰的兩個(gè)調(diào)用存在著調(diào)用關(guān)系。晚進(jìn)入堆棧的調(diào)用被早進(jìn)入堆棧的調(diào)用所調(diào)用。 此堆棧中最早被推入的調(diào)用是對(duì)應(yīng)協(xié)程的啟動(dòng)調(diào)用。
      • 另一個(gè)堆棧是上面提到的延遲調(diào)用堆棧。處于延遲調(diào)用堆棧中的任意兩個(gè)調(diào)用之間不存在調(diào)用關(guān)系。

      defer函數(shù)參數(shù)估值

      • 對(duì)于一個(gè)延遲函數(shù)調(diào)用,它的實(shí)參是在此調(diào)用被推入延遲調(diào)用堆棧的時(shí)候被估值的。
      • 一個(gè)匿名函數(shù)體內(nèi)的表達(dá)式是在此函數(shù)被執(zhí)行的時(shí)候才會(huì)被逐個(gè)估值的,不管此函數(shù)是被普通調(diào)用還是延遲調(diào)用。
        例子1:
      package mainimport  "fmt"func  Print(a int) {fmt.Println("defer函數(shù)中a的值=", a)}func  main() {a := 10defer  Print(a)a = 1000fmt.Println("a的值=", a)}

      output:

      a的值= 1000 defer函數(shù)中a的值= 10

      defer Print(a) 被加入到延遲調(diào)用堆棧的時(shí)候,a 的值是5,故defer Print(a) 輸出的結(jié)果為5
      例子2:

      package mainimport "fmt"func main() {     func() {         for i := 0; i < 3; i++ {             defer fmt.Println("a=", i)         }     }()      fmt.Println()     func() {         for i := 0; i < 3; i++ {             defer func() {                 fmt.Println("b=", i)             }()         }     }()}

      output:

      a= 2 a= 1 a= 0  b= 3 b= 3 b= 3

      第一個(gè)匿名函數(shù)循環(huán)中的 i 是在 fmt.Println函數(shù)調(diào)用被推入延遲調(diào)用堆棧的時(shí)候估的值,因此輸出結(jié)果是 2,1,0 , 第二個(gè)匿名函數(shù)中的 i 是匿名函數(shù)調(diào)用退出階段估的值(此時(shí) i 已經(jīng)變成3了),故結(jié)果輸出:3,3,3。
      其實(shí)對(duì)第二個(gè)匿名函數(shù)調(diào)用略加修改,就能使它輸出和匿名函數(shù)一相同的結(jié)果:

      package mainimport "fmt"func main() {     func() {         for i := 0; i < 3; i++ {             defer fmt.Println("a=", i)         }     }()      fmt.Println()     func() {         for i := 0; i < 3; i++ {             defer func(i int) {                 fmt.Println("b=", i)             }(i)         }     }()}

      output:

      a= 2 a= 1 a= 0  b= 2 b= 1 b= 0

      恐慌(panic)和恢復(fù)(defer + recover)

      Go不支持異常拋出和捕獲,而是推薦使用返回值顯式返回錯(cuò)誤。 不過(guò),Go支持一套和異常拋出/捕獲類(lèi)似的機(jī)制。此機(jī)制稱(chēng)為恐慌/恢復(fù)(panic/recover)機(jī)制。

      我們可以調(diào)用內(nèi)置函數(shù)panic來(lái)產(chǎn)生一個(gè)恐慌以使當(dāng)前協(xié)程進(jìn)入恐慌狀況。

      進(jìn)入恐慌狀況是另一種使當(dāng)前函數(shù)調(diào)用開(kāi)始返回的途徑。 一旦一個(gè)函數(shù)調(diào)用產(chǎn)生一個(gè)恐慌,此函數(shù)調(diào)用將立即進(jìn)入它的退出階段,在此函數(shù)調(diào)用中被推入堆棧的延遲調(diào)用將按照它們被推入的順序逆序執(zhí)行。

      通過(guò)在一個(gè)延遲函數(shù)調(diào)用之中調(diào)用內(nèi)置函數(shù)recover,當(dāng)前協(xié)程中的一個(gè)恐慌可以被消除,從而使得當(dāng)前協(xié)程重新進(jìn)入正常狀況。

      在一個(gè)處于恐慌狀況的協(xié)程退出之前,其中的恐慌不會(huì)蔓延到其它協(xié)程。 如果一個(gè)協(xié)程在恐慌狀況下退出,它將使整個(gè)程序崩潰??聪旅娴膬蓚€(gè)例子:

      package mainimport (     "fmt"     "time")func p(a, b int) int {     return a / b}func main() {     go func() {         fmt.Println(p(1, 0))     }()     time.Sleep(time.Second)     fmt.Println("程序正常退出~~~")}

      output:

      panic: runtime error: integer pide by zero  goroutine 6 [running]: main.p(...)         /Users/didi/Desktop/golang/defer.go:9 main.main.func1()         /Users/didi/Desktop/golang/defer.go:14 +0x12 created by main.main         /Users/didi/Desktop/golang/defer.go:13 +0x39exit status 2

      p函數(shù)發(fā)生panic(除數(shù)為0),因?yàn)樗趨f(xié)程沒(méi)有恐慌恢復(fù)機(jī)制,導(dǎo)致整個(gè)程序崩潰。
      如果p函數(shù)所在協(xié)程加上恐慌恢復(fù)(defer + recover),程序便可正常退出。

      package mainimport (     "fmt"     "time")func p(a, b int) int {     return a / b}func main() {     go func() {         defer func() {             v := recover()             if v != nil {                 fmt.Println("恐慌被恢復(fù)了:", v)             }         }()         fmt.Println(p(1, 0))     }()     time.Sleep(time.Second)     fmt.Println("程序正常退出~~~")}

      output:

      恐慌被恢復(fù)了: runtime error: integer pide by zero 程序正常退出~~~

      贊(0)
      分享到: 更多 (0)
      網(wǎng)站地圖   滬ICP備18035694號(hào)-2    滬公網(wǎng)安備31011702889846號(hào)