当前位置 博文首页 > 浅谈Go语言的error类型

    浅谈Go语言的error类型

    作者:fwhezfwhez 时间:2021-02-04 15:16

    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, 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 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, 0, 0, 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, error) {
     if code == 1 {
     return -1, &MsgError{code, "struct msg test error"}
     }
     return code, nil
    }
    func main() {
     for _, v := range []int{1, 2, 3, 4, 5, 6} {
      if code, err := f1(v); err != nil {
     fmt.Println(err)
     } else {
     fmt.Println("success:", code)
     }
     }
     for _, i := range []int{1, 2, 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

    以上为个人经验,希望能给大家一个参考,也希望大家多多支持站长博客。如有错误或未考虑完全的地方,望不吝赐教。

    js
    下一篇:没有了