• 企业400电话
  • 微网小程序
  • AI电话机器人
  • 电商代运营
  • 全 部 栏 目

    企业400电话 网络优化推广 AI电话机器人 呼叫中心 网站建设 商标✡知产 微网小程序 电商运营 彩铃•短信 增值拓展业务
    浅析golang开发Error的使用详解

    Error是Go语言开发中最基础也是最重要的部分,跟其他语言的try catch的作用基本一致,想想在PHP JAVA开发中,try catch 不会使用,或者使用不灵活,就无法感知到程序运行中出现了什么错误,是特别可怕的一件事。

    Error 基础

    Golang中 error类型就是一个最基本interface,定义了一个Error()的方法

    type error interface {
    	Error() string
    }

    平常使用最多的是这样的

    errors.New("error")

    在Golang中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()方法,所以实现了error interface

    看下Error在项目开发中是怎么使用的?

    1.定义Error变量

    在一段代码里面可能返回了很多个error,我怎么判断这个error是哪一种呢?
    是这样的吧

    var ERR_MSG = "error"
    if err.Error() == ERR_MSG

    这样的话,多个第三方类库和自己项目的错误描述要是一致的话就无法比较出来了,其实不应该是这样的。
    我们看下 beego里面orm是怎么定义的,从上面的基础我们知道errors.New返回的是errorString的指针

    var (
    	ErrTxHasBegan    = errors.New("Ormer.Begin> transaction already begin")
    	ErrTxDone        = errors.New("Ormer.Commit/Rollback> transaction not begin")
    	ErrMultiRows     = errors.New("QuerySeter> return multi rows")
    	ErrNoRows        = errors.New("QuerySeter> no row found")
    	ErrStmtClosed    = errors.New("QuerySeter> stmt already closed")
    	ErrArgs          = errors.New("Ormer> args error may be empty")
    	ErrNotImplement  = errors.New("have not implement")
    )

    其实都是使用指针判断的

    看下怎么使用,下面是伪代码

    err := this.QueryTable(this.table).Filter("id", id).One(data)
    if err != nil  err != orm.ErrNoRows {
    	return err
    }
    return nil

    这种其实在Golang 源码或者第三方类库里面用的比较多,缺点就是耦合,调用者使用一个第三方类库,需要知道的它的代码里面的错误类型,而且还需要在项目中使用这些错误类型的变量进行比较,第一次使用的开发者,很难想到需要这么使用。

    2.自定义自己的Error

    以前PHP的项目Exception里面会定义自己的错误码 code。
    Golang中我们也可以定义自己的Error类型,然后使用断言决定是那种Error来获取更多的错误数据,看下下面的示例代码,了解下自定义Error的简单使用

    type SelfError struct {
    	Code int
    	Err error
    }
    
    func (this *SelfError) Error() string {
    	return this.Err.Error()
    }
    func (this *SelfError) GetCode() int {
    	return this.Code
    }
    
    func OpenFile(name string) error {
    	err := os.Rename("/tmp/test","/tmp/test1")
    	if err != nil {
    		return SelfError{-1001, err}
    	}
    	return nil
    }
    
    func main() {
    	err := OpenFile("test")
    	switch erro := err.(type) {
    	case nil:
    		fmt.Println("success")
    	case *SelfError:
    		fmt.Println(erro.Error(),erro.Code)
    	case error:
    		fmt.Println(erro.Error())
    	}
    }

    还有一种用法就是判断error类型是否是自定义如果是,就返回自定义的属性

    func main() {
    	err := OpenFile("test")
    	serr, ok := err.(*SelfError)
    	if ok {
    		fmt.Println(serr.GetCode())
    	}
    }

    可以看到都是通过断言去判断error是否是自定义的Error,如果是,就使用自定义的Error自己的属性和方法。

    耦合,调用者需要使用switch或者断言才能使用自定义的Error的属性。

    3.Wrap Errors的使用

    wrap errors的使用应该是项目对error的处理运用最多的一种,可以方便的加入使用时的上下文。
    Wrap Errors 顾名思义就是把error一层层的包装,最外层拿到的是error的一个堆栈信息,根据堆栈信息一直可以追踪到第一个引起error 的调用代码。
    需要使用这个包

    github.com/pkg/errors

    看下代码示例

    package main
    
    import (
    	"fmt"
    	"github.com/pkg/errors"
    	"os"
    )
    
    func ModelFile() error {
    	err := os.Rename("/tmp/test","/tmp/test1")
    	if err != nil {
    		return errors.Wrap(err, "model_rename_fail")
    	}
    	return nil
    }
    
    func LogicFile() error {
    	err := ModelFile()
    	if err != nil {
    		return errors.Wrap(err, "logic_rename_fail")
    	}
    	return nil
    }
    
    func main() {
    	err := LogicFile()
    	if err != nil {
    		fmt.Printf("error:%v", errors.Cause(err))
    		fmt.Printf("%+v", err)
    	}
    }

    看下执行结果的堆栈

    error:rename /tmp/test /tmp/test1: no such file or directoryrename /tmp/test /tmp/test1: no such file or directory
    model_rename_fail
    main.ModelFile
            /data/www/go/src/test1/main.go:12
    main.LogicFile
            /data/www/go/src/test1/main.go:18
    main.main
            /data/www/go/src/test1/main.go:26
    runtime.main
            /usr/local/go/src/runtime/proc.go:203
    runtime.goexit
            /usr/local/go/src/runtime/asm_amd64.s:1357
    logic_rename_fail
    main.LogicFile
            /data/www/go/src/test1/main.go:20
    main.main
            /data/www/go/src/test1/main.go:26
    runtime.main
            /usr/local/go/src/runtime/proc.go:203
    runtime.goexit
            /usr/local/go/src/runtime/asm_amd64.s:1357

    使用的简单规则

    这么多使用方法,到底应该用哪一种,大致建议应该是这样的

    到此这篇关于浅析golang开发Error的使用的文章就介绍到这了,更多相关golang Error的使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

    您可能感兴趣的文章:
    • GO语言标准错误处理机制error用法实例
    • Go 自定义error错误的处理方法
    • golang 打印error的堆栈信息操作
    • 浅谈Go语言的error类型
    • Go应用中优雅处理Error的技巧总结
    上一篇:Mac下Vs code配置Go语言环境的详细过程
    下一篇:Golang 标准库 tips之waitgroup详解
  • 相关文章
  • 

    © 2016-2020 巨人网络通讯 版权所有

    《增值电信业务经营许可证》 苏ICP备15040257号-8

    浅析golang开发Error的使用详解 浅析,golang,开发,Error,的,