『Go 內置庫第一季:error』

VS CODE GOPHER.png

你們好,我叫謝偉,是一名程序員。程序員

近期我會持續更新內置庫的學習筆記,主要參考的是文檔 godoc 和 內置庫的源碼後端

本節的主題:errorbash

Go 中的錯誤處理和別的語言不同,設計哲學也不同,常有開發者埋怨 Go 語言中的錯誤處理。學習

本節從內置庫的 error 出發,結合內置庫的經常使用的 錯誤處理手法,總結出適合項目的錯誤處理方式。ui

大綱

  • 本身的經常使用的 error 錯誤處理方式
  • 內置庫實現的 error
  • 總結

本身的總結經常使用的 error 錯誤處理方式

1. 建立 error 類型的值spa

  • errors.New()
  • fmt.Errorf()

這兩個方法便可實現。設計

package main

import (
	"errors"
	"fmt"
	"reflect"
)

func main() {

	recordError := errors.New("record not found")
	dbError := fmt.Errorf("%s", "db connet fail")
	fmt.Println(recordError, reflect.TypeOf(recordError))
	fmt.Println(dbError, reflect.TypeOf(dbError))

}
>>
record not found *errors.errorString
db connet fail *errors.errorString

複製代碼

2. 自定義錯誤類型code

  • 實現 error 接口
type CodeError struct {
	Code    int
	Message string
}

func (c CodeError) Error() string {
	return fmt.Sprintf(" e.Code = %d, e.Message=%s", c.Code, c.Message)
}

func Result() error {
	var codeError CodeError
	codeError = CodeError{
		Code:    400,
		Message: "connect fail",
	}
	return codeError
}

func main(){
    
    var codeError CodeError
	var err error
	codeError = CodeError{
		Code:    404,
		Message: "http status code error",
	}
	err = codeError
    fmt.Println(err)
}
>>
e.Code = 404, e.Message=http status code error
複製代碼

本身定義的錯誤類型,只要實現了 error 接口便可。orm

能夠看下具體的 接口定義:cdn

type error interface {
	Error() string
}

複製代碼
  • errors.New 的具體實現
func New(text string) error {
	return &errorString{text}
}

// errorString is a trivial implementation of error.
type errorString struct {
	s string
}

func (e *errorString) Error() string {
	return e.s
}
複製代碼

即 定義了 errorString 結構體, 綁定了 Error 方法

  • fmt.Errorf 的具體實現
func Errorf(format string, a ...interface{}) error {
	return errors.New(Sprintf(format, a...))
}
複製代碼

即 fmt.Errorf 調用的也是 errors.New 方法。

總結上文:

  1. 建立 error 存在兩種方法
  2. 底層 是一個結構體實現了 error 接口
  3. 自定義的錯誤類型,實現 Error 方法便可

內置庫實現的 error

錯誤很常見,是業務的一部分,那麼內置的庫在實現時也會遇到錯誤,看內置庫是如何實現的 error

1. strconv.Atoi

func main(){
    
    number, err := strconv.Atoi("2992-121")
    fmt.Println(number,err)
}
>>
0 strconv.Atoi: parsing "2992-121": invalid syntax
複製代碼

具體的底層實現是:

type NumError struct {
	Func string // the failing function (ParseBool, ParseInt, ParseUint, ParseFloat)
	Num  string // the input
	Err  error  // the reason the conversion failed (e.g. ErrRange, ErrSyntax, etc.)
}

func (e *NumError) Error() string {
	return "strconv." + e.Func + ": " + "parsing " + Quote(e.Num) + ": " + e.Err.Error()
}
複製代碼

定義各類錯誤類型:

var ErrRange = errors.New("value out of range")
var ErrSyntax = errors.New("invalid syntax")
func syntaxError(fn, str string) *NumError {
	return &NumError{fn, str, ErrSyntax}
}

func rangeError(fn, str string) *NumError {
	return &NumError{fn, str, ErrRange}
}

func baseError(fn, str string, base int) *NumError {
	return &NumError{fn, str, errors.New("invalid base " + Itoa(base))}
}

func bitSizeError(fn, str string, bitSize int) *NumError {
	return &NumError{fn, str, errors.New("invalid bit size " + Itoa(bitSize))}
}
複製代碼

即:核心是定義了一個結構體,實現了 error 接口

2. net/http

func main(){
    
	response, err := http.Get("https://space.bilibili.com/10056291/#/")
	fmt.Println(response, err)
    
}

複製代碼

底層的錯誤類型是:

type Error struct {
	Op  string
	URL string
	Err error
}

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

複製代碼

即定義了一個結構體,實現的 error 接口。

鑑於對內置庫的底層的 錯誤類型的閱讀,修改本身設置錯誤類型的方法:以下

type ExampleError struct {
	Err     error
	Code    int
	Message string
}

func (e *ExampleError) Error() string {
	return fmt.Sprintf("e.Code = %d e.Err = %s e.Message = %s", e.Code, e.Err.Error(), e.Message)
}

func ExampleResult() error {
	return &ExampleError{
		Err:     errors.New("what the fucking life"),
		Code:    502,
		Message: "what the fucking life",
	}
}
複製代碼

總結

  • 建立 error 值存在兩種方法
  • 本身定義的錯誤類型,只需實現 Error 方法,實現 error 接口便可

其餘:對錯誤的處理還有這些建議

  • 每一個庫,能夠在庫文件的開頭聲明常見的錯誤
var ErrorIndexOut = errors.New("index out of range")
var ErrorFuck = errors.New("fucking life")
複製代碼
  • 錯誤類型的變量能夠帶上 Err 或者 Error 標示
  • 建議統一處理錯誤類型,即,完整的項目在聲明本身的庫處理模塊,而不是隨意的在項目內建立 error

<完>

相關文章
相關標籤/搜索