1. 程式人生 > 程式設計 >淺談Go語言的error型別

淺談Go語言的error型別

error型別是go語言的一種內建型別,使用的時候不用特定去import,他本質上是一個介面

 type error interface{
 Error() string //Error()是每一個訂製的error物件需要填充的錯誤訊息,可以理解成是一個欄位Error
}

怎樣去理解這個訂製呢?

我們知道介面這個東西,必須擁有它的實現塊才能呼叫,放在這裡就是說,Error()必須得到填充,才能使用.

比方說下面三種方式:

第一種:通過errors包去訂製error

error := errors.New("hello,error")//使用errors必須import "errors"包
if error != nil {
 fmt.Print(err)
}

來解釋一下errors包,只是一個為Error()填充的簡易封裝,整個包的內容,只有一個New方法,可以直接看

func New(text string) error

第二種:通過fmt.Errorf()去訂製

err := fmt.Errorf("hello error")
if err != nil {
 fmt.Print(err)
}

可以說和第一種雷同了.

第三種:就是通過自定義的MyError塊去訂製了

//一個包裹了錯誤型別物件的自定義錯誤型別
type MyError struct {
err error 
}
//訂製Error()
func (e MyError) Error() string {
 return e.err.Error()
}
func main() {
 err:=MyError{
 errors.New("hello error"),}
 fmt.Println(err.Error())
}

三種方式差異都不大,輸出結果都是 hello error

實際上error只是一段錯誤資訊,真正丟擲異常並不是單純靠error,panic和recover的用法以後總結。

補充:go error介面與errors包詳解

1 error介面

定義:

 type error interface{
 Error() string //Error()是一個方法,是每一個訂製的error物件需要填充的錯誤訊息,可以理解成是一個欄位Error
}

1.1 常見呼叫方式

模板

n,err := Foo(0) 
 
if err != nil { 
 // 錯誤處理 
} else { 
 // 使用返回值 n 
} 

練習1

package main
import ( 
 "fmt"
 "os"
)
func main() { 
 f,err := os.Open("/test.txt")
 if err != nil {
  fmt.Println(err)
  return
 }
 fmt.Println(f.Name(),"opened successfully")
}

[root@localhost error]# go run err3.go

open /test.txt: no such file or directory

1.2 自定義error方法

1.2.1 函式呼叫error

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

1.2.2 自定義Error模板1

type fileError struct {
}
func (fe *fileError) Error() string {
 return "檔案錯誤"
}

練習1

模擬一個錯誤

package main
import "fmt"
type fileError struct {
}
func (fe *fileError) Error() string { //自定義會覆蓋原來的Error介面
 return "檔案錯誤"
}
//只是模擬一個錯誤
func openFile() ([]byte,error) {
 return nil,&fileError{}
}
func main() {
 conent,err := openFile()
 if err != nil {
  fmt.Println(err)
 } else {
  fmt.Println(string(conent))
 }
}

[root@localhost error]# go run err1.go

檔案錯誤

1.2 自定義Error模板2

自定義中新增一個字串

type fileError struct {
 s string
}
func (fe *fileError) Error() string {
 return fe.s
}

練習2

宣告fileError的時候,設定好要提示的錯誤文字

package main
import "fmt"
type fileError struct {
 s string
}
func (fe *fileError) Error() string {
 return fe.s
}
//只是模擬一個錯誤
func openFile() ([]byte,&fileError{"檔案錯誤,自定義"} 
}
func main() {
 conent,err := openFile()
 if err != nil {
  fmt.Println(err)
 } else {
  fmt.Println(string(conent))
 }
}

[root@localhost error]# go run err2.go

檔案錯誤,自定義

練習3

新增一個時間刻度

package main
import (
 "fmt"
 "time"
)
type MyError struct {
 When time.Time
 What string
}
func (e MyError) Error() string {
 return fmt.Sprintf("%v: %v",e.When,e.What)
}
func oops() error {
 return MyError{
  time.Date(1989,3,15,22,30,time.UTC),"the file system has gone away",}
}
func main() { 
 if err := oops(); err != nil { 
  fmt.Println(err) 
 }
}

[root@localhost error]# go run err4.go

1989-03-15 22:30:00 +0000 UTC: the file system has gone away

練習三

沒有開啟檔案報錯

package main
import (
 "fmt"
 "os"
)
type PathError struct {
 Op string
 Path string
 Err error
}
func (e *PathError) Error() string { 
  return e.Op + " " + e.Path + ": " + e.Err.Error() 
} 
func main() {
 f,err := os.Open("/test.txt")
 if errObject,ok := err.(*os.PathError); ok {
 fmt.Println("錯誤輸出:",err,"檔案路徑:",errObject.Path)
 return
 }
 fmt.Println(f.Name(),"opened successfully")
} 

[root@localhost error]# go run err5.go

錯誤輸出: open /test.txt: no such file or directory 檔案路徑: /test.txt

2 errors包

2.1 獲取error包

go get github.com/pkg/errors

2.2 errors.New()

errors.New()接收合適的錯誤資訊來建立

先宣告再使用

l練習1

package main
import (
 "errors"
 "fmt"
)
var errNotFound error = errors.New("Not found error")
func main() {
 fmt.Printf("error: %v",errNotFound)
}

[root@localhost error]# go run errs1.go

error: Not found error

練習2

函式如何呼叫err

直接使用

package main
import (
 "errors"
 "fmt"
)
func Sqrt(f float64) (float64,error) {
  if f < 0 {
   return 0,errors.New("math - square root of negative number")
  }else {
   return 1,errors.New("math - square root of 10")
  }
}
func main() {
 if _,err := Sqrt(-1); err != nil {
  fmt.Printf("Error: %s\n",err)
 }
}

[root@localhost error]# go run errs2.go

Error: math - square root of negative number

3 自定義error與errors.New()使用比較

比較自定義error與errors.New()函式根據需求其實各有優點。

package main
import (
 "errors"
 "fmt"
)
type MsgError struct {
 Code int
 Msg string
}
func (msg *MsgError) Error() string {
 return fmt.Sprintf("%s",msg.Msg)
}
func f1(code int) (int,error) {
 if code == 1 {
 return -1,errors.New("msg test error")
 }
 return code,nil
}
func f2(code int) (int,&MsgError{code,"struct msg test error"}
 }
 return code,nil
}
func main() {
 for _,v := range []int{1,2,4,5,6} {
  if code,err := f1(v); err != nil {
 fmt.Println(err)
 } else {
 fmt.Println("success:",code)
 }
 }
 for _,i := range []int{1,3} {
 if code,err := f2(i); err != nil {
 fmt.Println(err)
 } else {
 fmt.Println("success:",code)
 }
 }
}
[root@localhost error]# go run errs3.go
msg test error
success: 2
success: 3
success: 4
success: 5
success: 6
struct msg test error
success: 2
success: 3

以上為個人經驗,希望能給大家一個參考,也希望大家多多支援我們。如有錯誤或未考慮完全的地方,望不吝賜教。