开发者

Go语音开发中常见Error类型处理示例详解

开发者 https://www.devze.com 2022-12-08 10:52 出处:网络 作者: bluesGavin
目录前言透明错误处理策略带来的问题哨兵(Sentinel)错误处理策略带来的问题1.对errors.Error()的依赖2.定义的错误类型会被公开Error types带来的问题不透明错误处理策略(Opaque errors)带来的问题总结前言
目录
  • 前言
  • 透明错误处理策略
    • 带来的问题
  • 哨兵(Sentinel)错误处理策略
    • 带来的问题
      • 1.对errors.Error()的依赖
      • 2.定义的错误类型会被公开
  • Error types
    • 带来的问题
    • 不透明错误处理策略(Opaque errors)
      • 带来的问题
      • 总结

        前言

        上文我们了解了 Error 在 Go 中的设计理念。单从理念上来看, Error 的设计似乎有利于逻辑处理。但实际上,在开发过程中,我们还会遇到各种各样的困难。为了优化开发的流程,开发者们发明了很多处理 Error 的做法。今天我们就来看看目前 Go 开发中常见的几大 Error 类型。

        透明错误处理策略

        在最简单的 Go Error 设计中,开发者被期望通过判定函数返回的 err 值来确定调用是否正常。

        value, err := DOSomething()
        if err != nil {
        	// 错误处理
        }
        // 逻辑操作
        

        这是 Go 语言中最常见的错误处理策略 ,80%以上的 Go 错误处理情形都可以归类到这种策略下。这样构造出的错误值代表的上下文信息,对错误处理方是透明的,因此这种策略称为 透明错误处理策略

        这种策略最大的问题是,无法判定错误的原因和种类。它只是简单地把”是否出错“分为了两路逻辑。一旦我们的业务要求我们针对不同的错误原因,做不同的处理,这种情况就行不通了。

        带来的问题

        透明策略只解决了”是否出错“的问题,但开发者无法知道错误的原因。如果想要得到错误的内容,需要主动解析error值,这也引出了下面要讲的处理策略。

        哨兵(Sentinel)错误处理策略

        哨兵策略策略主要是解决透明错误处理策略精度不够的情况,它可以让开发者得到“是什么错误”,而不仅是”是否出错“。实际上,它就是通过预定义错误类型,在错误处理时,判断错误是否属于预定义的类别,从而做出处理。

        因此我们可以得到它最简单的实现:

        value, err := doSomething()
        if err!=nil { 
            // 通过err.Error()获得错误信息
            switch err.Error(){ 
                case "bufio: negative count": 
                	//特点错误处理 
                	return 
                // 其他判断
                default: 
                	// 未知错误原因
                	return 
            } 
        }
        

        但这显然不是好的写法,会导致很严重的耦合问题。Go 1.13 之后,我们可以用 error.Is 方法很好地解决这个问题。

        // 定义错误类型,一般变量用Err开头
        var(
          ErrInvalidUnreadByte=errors.New("bufio编程客栈: invalid use of UnreadByte")ErrInvalidUnreadRune=errors.New("bufio: invalhttp://www.devze.comid use of UnreadRune")
          ErrBufferFull=errors.New("bufio: buffer full")
          ErrNegativeCount=errors.New("bufio: negative count")
        )
        
        func main(){
        	value, err := doSomething()
          	if errors.Is(err,ErrBufferFull){
            	//判断是否为某类型错误
          	}
        }
        

        带来的问题

        虽然哨兵策略解决了我们不能获得错误原因的问题,但它本身也存在着设计缺陷。

        1.对errors.Error()的依赖

        == 的判断依赖着 errors.Error() 的输出。这是哨兵策略最大的问题。他导致了 error 值的扩展性很差,假如开发者想要为 error 带上上下文或者错误行号,文件位置等信息,都会破坏哨兵策略的判断。

        从某种角度来看,errors.Error() 的输出更应该是用于开发者的调试使用,而不应该作为程序判断机制的一部分。

        2.定义的错误类型会被公开

        很多时候为了做错误类型判断,一些包内需要定义许多错误类型。而这些错误类型通常会被共用,这使得他们不得不被公开。在公共库中,被公开的错误类型必须有专门的文档说明,否则会对使用者造成困惑。这会额外增加开发者的工作量。

        再者,有时为了判断某个特殊错误类型,使用者会引入对应的包。假如这种情况大量存在,会导致整个库生态极其混乱。

        Error types

        Error types 是实现了 errors 接口的自定义类型,目的是为了更加具体地描述错误。开发者可以在类型上带上需要的信息,如行号,文件位置等。可以参考下方:

        type MyError struct {
            Msg string	// 错误信息
            Line int	// 行号
            FIle string // 文件位置
        }
        
        // 实现 errors 接口
        func (e *MyError) Error()string{
            return fmt.Sprintf("%s:%d: js%s",e.File,e.Line,e.Msg)
        }
            
        

        上面提到,修改 error 值会导致哨兵策略的失效, Error types 就是例子之一。由于是自定义的类型,我们不能再用 == 判断错误类型了,而是改用断言。

        value, ok := x.(MyError)
        if ok {
            //判断是否为某类型错误
        }
        

        带来的问题

        可以看到 Error Types 最大的优势是其丰富的错误描述能力。但它仍然没有解决哨兵策略下的问题。

        不透明错误处理策略(Opaque errors)

        不透明错误处理策略可以说是最灵活的处理方式,它要求代码与调用者之间的耦合最少。开发者可以知道”是否出错“,但无法得到错误的内部信息。

        value, err := doSomething()
        if err != nil {
        	// 错误处理
        }
        // 逻辑操作
        

        是的,在使用上不透明策略透明策略是很相似的。其中最大的不同是,透明策略可以通过 error.Error() 接口获得错误信息。而不透明策略中是不可以的。

        那如果开发者需要判断错误类型怎么办呢?不透明策略更推荐的是断言 error 实现的行为,而不是特定的类型或值。可以参考下方代码:

        type temporary interface {
            Temporary() bool
        }
        // 封装判断函数
        func I编程客栈sTemporary(err error) bool {
            // 断言
            te, ok := err.(temporay)
            // 是否满足条件
            return ok && te.Temporary()
        }
        

        带来的问题

        不透明策略跟透明策略一样,是很灵活的策略。他们的区别只在于错误的信息是否开放。因此,不透明策略依旧存在信息量缺乏的问题。

        总结

        今天我们了解了目前开发者_JAVA开发 Go 开发中常见的四种 Error 类型。这些类型编程客栈各有优劣,需要开发者在实际开发者中深入思考,做出取舍。通常我们需要考虑,我们开发的是工具还是业务,我们需要错误为我们提供灵活度还是精确的信息。掌握本文的内容,可以让你在遇到错误处理时,有更多的处理思路。

        当然,每种方式又会有问题,在接下来的文章里,我会分享一些常见的错误处理操作。

        以上就是Go语音开发中常见Error类型处理示例详解的详细内容,更多关于Go语音Error类型的资料请关注我们其它相关文章!

        0

        精彩评论

        暂无评论...
        验证码 换一张
        取 消

        关注公众号