你們好,我叫謝偉,是一名程序員。程序員
近期我會持續更新內置庫的學習筆記,主要參考的是文檔 godoc 和 內置庫的源碼後端
本節的主題:errorbash
Go 中的錯誤處理和別的語言不同,設計哲學也不同,常有開發者埋怨 Go 語言中的錯誤處理。學習
本節從內置庫的 error 出發,結合內置庫的經常使用的 錯誤處理手法,總結出適合項目的錯誤處理方式。ui
1. 建立 error 類型的值spa
這兩個方法便可實現。設計
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
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
}
複製代碼
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 方法
func Errorf(format string, a ...interface{}) error {
return errors.New(Sprintf(format, a...))
}
複製代碼
即 fmt.Errorf 調用的也是 errors.New 方法。
總結上文:
錯誤很常見,是業務的一部分,那麼內置的庫在實現時也會遇到錯誤,看內置庫是如何實現的 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",
}
}
複製代碼
其餘:對錯誤的處理還有這些建議
var ErrorIndexOut = errors.New("index out of range")
var ErrorFuck = errors.New("fucking life")
複製代碼
Err
或者 Error
標示<完>