<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>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ### defer陷阱 #### 1. defer 與 closure ~~~ func foo(a, b int) (i int, err error) { defer fmt.Printf("first defer err %v\n", err) defer func(err error) { fmt.Printf("second defer err %v\n", err) }(err) defer func() { fmt.Printf("third defer err %v\n", err) }() if b == 0 { err = errors.New("divided by zero!") return } i = a / b return } 輸出結果: third defer err divided by zero! second defer err <nil> first defer err <nil> ~~~ 解釋:如果 defer 后面跟的不是一個 closure 最后執行的時候我們得到的并不是最新的值 #### 2. defer 與 return ~~~ func foo() (i int) { i = 0 defer func() { fmt.Println(i) }() return 2 } 輸出結果: 2 ~~~ 解釋:在有具名返回值的函數中(這里具名返回值為 i),執行 return 2 的時候實際上已經將 i 的值重新賦值為 2。所以defer closure 輸出結果為 2 而不是 1 #### 3. defer nil 函數 ~~~ func test() { var run func() = nil defer run() fmt.Println("runs") } func main() { defer func() { if err := recover(); err != nil { fmt.Println(err) } }() test() } 輸出結果: runs runtime error: invalid memory address or nil pointer dereference ~~~ 解釋:名為 test 的函數一直運行至結束,然后 defer 函數會被執行且會因為值為 nil 而產生 panic 異常。然而值得注意的是,run() 的聲明是沒有問題,因為在test函數運行完成后它才會被調用 #### 4. 在錯誤的位置使用 defer 當 http.Get 失敗時會拋出異常。 ~~~ func do() error { res, err := http.Get("http://www.google.com") defer res.Body.Close() if err != nil { return err } // ..code... return nil } 輸出結果: panic: runtime error: invalid memory address or nil pointer dereference ~~~ 解釋:因為在這里我們并沒有檢查我們的請求是否成功執行,當它失敗的時候,我們訪問了 Body 中的空變量 res ,因此會拋出異常 #### recover使用誤區 在項目中,有眾多的數據庫更新操作,正常的更新操作需要提交,而失敗的就需要回滾,如果異常分支比較多, 就會有很多重復的回滾代碼,所以有人嘗試了一個做法:即在defer中判斷是否出現異常,有異常則回滾,否則提交。 簡化代碼如下所示: ~~~golang func IsPanic() bool { if err := recover(); err != nil { fmt.Println("Recover success...") return true } return false } func UpdateTable() { // defer中決定提交還是回滾 defer func() { if IsPanic() { // Rollback transaction } else { // Commit transaction } }() // Database update operation... } ~~~ `func IsPanic() bool`用來接收異常,返回值用來說明是否發生了異常。`func UpdateTable()`函數中,使用defer來判斷最終應該提交還是回滾。 上面代碼初步看起來還算合理,但是此處的`IsPanic()`再也不會返回`true`,不是`IsPanic()`函數的問題,而是其調用的位置不對 **recover 失效的條件** 上面代碼`IsPanic()`失效了,其原因是違反了recover的一個限制,導致recover()失效(永遠返回`nil`)。 以下三個條件會讓recover()返回`nil`: 1. panic時指定的參數為`nil`;(一般panic語句如`panic("xxx failed...")`) 2. 當前協程沒有發生panic; 3. recover沒有被defer方法直接調用; 本例中,recover() 調用棧為“defer (匿名)函數” –> IsPanic() –> recover()。也就是說,recover并沒有被defer方法直接調用。符合第3個條件,所以recover() 永遠返回nil
                  <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>

                              哎呀哎呀视频在线观看