Go-error理论部分

将每一大块知识点,整理出一个理论部分和一个实践部分,实践部分就是工作中遇到的相关的话题。

1.error 与 exception

go 的 error 就是一个接口,一个值,通常用error.news 来定义一个error

	var byZero = errors.New("divide no zero")
	var byZero1 = errors.New("divide no zero")

	if byZero == byZero1 {
		println("yes")
	} else {
		println("no")
	}
	//errors.new 返回内部的errorString 但是是指针,这里防止了两个string错误描述一模一样的情况。

如果一个函数返回了 value, error,你不能对这个 value 做任何假设,必须先判定 error。唯一可以忽略 error 的是,如果你连 value 也不关心,对于真正的异常,go预留了panic,fatal error 这个不能假设调用者做任何处理
对于真正意外的情况,那些表示不可恢复的程序错误,例如索引越界、不可恢复的环境问题、栈溢出,我们才使用 panic。对于其他的错误情况,我们应该是期望使用 error 来进行判定。

  1. 简单
  2. 考虑失败,而不是成功(Plan for failure, not success)
  3. 没有隐藏的控制流
  4. 完全交给你来控制 error
  5. Error are values

2. error 类型

  1. 哨兵形式,先预留可能出现的error 然后作对比 if err ==…
    这种方式使得error无法携带更多的上下文,我们不应该依赖error的输出,这个输出更多是给日志和排查使用的
    2.自定义结构体的形式
    这个方式可以携带更多的上下文了,并且可以通过断言的形式判断error的类型,例如:
// 实现Error方法
type MyError struct {
	line int
	des string
}
func (e *MyError) Error() string {
	return fmt.Sprintf("line is %d, content is %s", e.line, e.des)
}

func test() error {
	return &MyError{4, "sth is error"}
}

// main 
	err := test()
	switch err := err.(type) {
	case nil:
		print("ok")
	case *MyError:
		print(err.line)
	default:
		print("unkonwn")
	}

这个方法调用者断言的时候需要知道你自定义的error类型,产生了耦合,万一哪天你一改
3.不透明的处理
发现error直接返回error 不对他做任何假设
但是如果不是这种简单的二分 做或者不做,那怎么办
在这种情况下,我们可以断言错误实现了特定的行为,而不是断言错误是特定的类型或值

(其实不太理解,hhh)在这里插入图片描述

3.处理error

无错误的正常流程代码,将成为一条直线,而不是缩进的代码
也就是一般判断 != nil
错误只需要处理一次,不处理的地方返回即可

  1. 自己代码中使用new 或者errorf
  2. 调用其他函数,直接rerurn err
  3. 如果和其他库进行协作,考虑使用 errors.Wrap 或者 errors.Wrapf 保存堆栈信息。同样适用于和标准库协作的时候
  4. errors.Cause 获取 root error,再进行和 sentinel error 判定
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值