Go的标準庫函數在發生錯誤時會傳回error類型,比如常用的os.Open函數用來打開檔案,錯誤時傳回error:
func Open(name string) (*File, error)
那麼究竟什麼是error類型呢?其實很簡單,error是一個接口,該接口隻聲明了一個方法Error(),傳回值是string類型,用以描述錯誤:
type error interface {
Error() string
}
如何建立自己的error呢?當然可以自己實作這個接口,比如:
package main
import "fmt"
type MyError struct {
Desc string
}
func (myErr MyError) Error() string {
return myErr.Desc
}
func doSomething() error {
// ...
return MyError{"Logic Error!"}
}
func main() {
if err := doSomething(); err != nil {
fmt.Println(err)
}
}
但是更簡單的方法是利用errors包中的New()函數直接建立error對象,errors包的内容僅有如下四行代碼:
package errors
func New(text string) error { return &errorString{text} }
type errorString struct { text string }
func(e *errorString) Error() string { return e.text }
可以看到errors包的内部聲明了一個 errorString 結構體,并用其中的text字段來表示錯誤描述,而不是直接用字元串來表示,這樣做的好處是将錯誤描述封裝了起來,防止我們在包外意外地改變錯誤描述。注意實作 error 接口的是 *errorString,而不是 errorString,這是為了讓所有New傳回的error對象都不相等:
一版情況下我們很少調用errors.New()來建立error對象,而是通過fmt包中提供的函數Errorf():
package fmt
import "errors"
func Errorf(format string, args ...interface{}) error {
return errors.New(Sprintf(format, args...))
}
可以看到fmt.Errorf()也是通過errors.New()來建立error對象。
*errorString 可能是最簡單的error對象,但并不是唯一的error對象,比如syscall包中的Errno也是一個實作了error接口的類型。在Unix實作中,Errno的Error()方法通過查找錯誤清單傳回錯誤資訊:
package syscall
type Errno uintptr
var errors = [...]string {
: "operation not permitted",
: "no such file or directory",
// ...
}
func (e Errno) Error() string {
if <= int(e) && int(e) < len(errors) {
return errors[e]
}
return fmt.Sprintf("errno %d", e)
}
參考自《Go程式設計語言》