<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Go 錯誤處理篇(一):error 類型及其使用

          共 4792字,需瀏覽 10分鐘

           ·

          2021-03-11 02:45

          一、Go 語言錯誤處理機制

          Go 語言錯誤處理機制非常簡單明了,不需要學(xué)習(xí)了解復(fù)雜的概念、函數(shù)和類型,Go 語言為錯誤處理定義了一個標準模式,即 error 接口,該接口的定義非常簡單:

          type error interface { 
              Error() string 
          }

          其中只聲明了一個 Error() 方法,用于返回字符串類型的錯誤消息。對于大多數(shù)函數(shù)或類方法,如果要返回錯誤,基本都可以定義成如下模式 —— 將錯誤類型作為第二個參數(shù)返回:

          func Foo(param int) (n int, err error) { 
              // ...
          }

          然后在調(diào)用返回錯誤信息的函數(shù)/方法時,按照如下「衛(wèi)述語句」模板編寫處理代碼即可:

          n, err := Foo(0)

          if err != nil { 
              // 錯誤處理 
          else {
              // 使用返回值 n 
          }

          非常簡潔優(yōu)雅。

          二、返回錯誤實例并打印

          關(guān)于自定義并返回 error 類型錯誤信息的使用示例,前面介紹函數(shù)多返回值時已經(jīng)演示過,我們可以通過 Go 標準錯誤包 errors 提供的 New() 方法快速創(chuàng)建一個 error 類型的錯誤實例:

          func add(a, b int) (c int, err error) {
              if (a &lt; 0 || b &lt; 0) {
                  err = errors.New("只支持非負整數(shù)相加")
                  return
              }
              a *= 2
              b *= 3
              c = a + b
              return
          }

          我們參照上面介紹的 Go 錯誤處理標準模式,調(diào)用這個函數(shù)并編寫錯誤處理的代碼如下:

          func main() {
              if len(os.Args) != 3 {
                  fmt.Printf("Usage: %s num1 num2\n", filepath.Base(os.Args[0]))
                  return
              }
              x, _ := strconv.Atoi(os.Args[1])
              y, _ := strconv.Atoi(os.Args[2])
              // 通過多返回值捕獲函數(shù)調(diào)用過程中可能的錯誤信息
              z, err := add(x, y)
              // 通過「衛(wèi)述語句」處理后續(xù)業(yè)務(wù)邏輯
              if err != nil {
                  fmt.Println(err)
              } else {
                  fmt.Printf("add(%d, %d) = %d\n", x, y, z)
              }
          }

          為了方便測試,我們將通過命令行參數(shù)傳遞 add 函數(shù)的參數(shù),這里我們引入了 os 包讀取命令行參數(shù),并通過 strconv 包提供的 Atoi 方法將其轉(zhuǎn)化為整型(命令行讀取參數(shù)值默認是字符串類型,轉(zhuǎn)化時忽略錯誤以便簡化處理流程),然后分別賦值為 x、y 變量,再調(diào)用 add 函數(shù)進行運算。

          注意到我們在打印錯誤信息時,直接傳入了 err 對象實例,因為 Go 底層會自動調(diào)用 err 實例上的 Error() 方法返回錯誤信息并將其打印出來,就像普通類的 String() 方法一樣。

          我們簡單測試下不傳遞參數(shù)、傳遞錯誤類型參數(shù)和傳遞正常參數(shù)這幾種場景,打印結(jié)果如下:

          以上這種錯誤處理已經(jīng)能夠滿足我們?nèi)粘>帉?Go 代碼時大部分錯誤處理的需求了,事實上,Go 底層很多包進行錯誤處理時就是這樣做的。此外,我們還可以通過 fmt.Errorf() 格式化方法返回 error 類型錯誤,其底層調(diào)用的其實也是 errors.New 方法:

          func Errorf(format string, a ...interface{}) error {
              return errors.New(Sprintf(format, a...))
          }

          三、更復(fù)雜的錯誤類型

          系統(tǒng)內(nèi)置錯誤類型

          除了上面這種最基本的、使用 errors.New() 方法返回包含錯誤信息的錯誤實例之外,Go 語言內(nèi)置的很多包還封裝了更復(fù)雜的錯誤類型。

          以 os 包為例,這個包主要負責(zé)與操作系統(tǒng)打交道,所以提供了 LinkError、PathErrorSyscallError 這些實現(xiàn)了 error 接口的錯誤類型,以 PathError 為例,顧名思義,它主要用于表示路徑相關(guān)的錯誤信息,比如文件不存在,其底層類型結(jié)構(gòu)信息如下:

          type PathError struct {
              Op   string
              Path string
              Err  error
          }

          該錯誤類型除了組合 error 接口實現(xiàn) Error() 方法外,還提供了額外的操作類型字段 Op 和文件路徑字段 Path 以豐富錯誤信息,方便定位問題,該類型的 Error() 方法實現(xiàn)如下:

          func (e *PathError) Error() string { 
              return e.Op + " " + e.Path + ": " + e.Err.Error() 
          }

          我們可以在調(diào)用 os 包方法出錯時通過 switch 分支語句判定具體的錯誤類型,然后進行相應(yīng)的處理:

          // 獲取指定路徑文件信息,對應(yīng)類型是 FileInfo
          // 如果文件不存在,則返回 PathError 類型錯誤
          fi, err := os.Stat("test.txt"
          if err != nil {
              switch err.(type) {
              case *os.PathError:
                  // do something
              case *os.LinkError:
                  // dome something
              case *os.SyscallError:
                  // dome something
              case *exec.Error:
                  // dome something
              }
          else {
              // ...
          }

          關(guān)于 os 包的更多使用細節(jié),我們將在后面 Go 系統(tǒng)編程中詳細介紹。

          自定義錯誤類型

          當然,我們也可以仿照 PathError 的實現(xiàn)自定義一些復(fù)雜的錯誤類型,只需要組合 error 接口并實現(xiàn) Error() 方法即可,然后按照自己的需要為自定義類型添加一些屬性字段,這很簡單,就不展開介紹了。

          四、小結(jié)

          可以看到,Go 語言的錯誤和其他語言的錯誤和異常不同,它們就是從函數(shù)或者方法中返回的、和其他返回值并沒有什么區(qū)別的普通 Go 對象而已,如果程序出錯,要如何處理程序下一步的動作,是退出程序還是警告后繼續(xù)執(zhí)行,決定權(quán)完全在開發(fā)者手上。

          (本文完)


          學(xué)習(xí)過程中有任何問題,可以通過下面的評論功能或加入「Go 語言研習(xí)社」與學(xué)院君討論:


          本系列教程首發(fā)在 geekr.dev,你可以點擊頁面左下角閱讀原文鏈接查看最新更新的教程。

          瀏覽 147
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青青视频在线免费观看 | 爱干视频| 久久久久成人免费视频 | 爱爱欧美| 黄色免费在线观看 |