深入理解与使用go之错误处理--实现

深入理解与使用go之错误处理–实现

引子

错误管理是构建健壮和可观察的应用程序的一个基本方面,它应该与代码库的任何其他部分一样重要。在Go中,错误管理不像大多数编程语言那样依赖于传统的try/catch机制。相反,错误作为正常返回值返回。那么问题来了:

  • 程序什么时候发生崩溃(panic)
  • 通常处理错误的方式是怎样的
  • 我们应该忽略错误么
  • 在defer里出错应该怎么处理呢
  • 所有的panic错误都是可以捕获的么

我记得刚写程序的时候,感觉对go的错误很茫然,一股脑的忽略错误,像下面这样

// json 解码
_ = json.Unmarshal(data, &User)
// 打开文件
f, _ := os.Open("hello")

或者,我们避无可避,选择这样判断错误

if strings.Contains(err.Error(), "op error") {
   
		return ""
}
return data
  • 如果json解码的是配置文件,忽略错误会直接导致整个程序启动崩溃
  • 打开文件如果没有权限,下面的所有操作直接panic
  • 如果A开发错误内容是小写 “op error” 而B开发是大写 “OP ERROR”, 能判断么

带着上面的这些问题,我们来讨论讨论今天要说的错误处理

错误处理

错误的分类

我觉得开始处理之前,我们很有必要对错误进行一定的分类

  1. 崩溃型错误
    • 系统调用出现的崩溃 如堆栈溢出、数组越界、空指针引用等等
    • 程序限制型崩溃,如初始化过程中的配置读取、日志路径权限等等,出现错误整个程序就不该继续往下走
  2. 普通型错误
    • 错误我们需要处理,比如数据库连接异常 我们进行重试
  3. 正常型错误
    • 数据库因为查询为空返回的错误
    • 文件读取到末尾的EOF错误
    • 我们不感兴趣且对程序执行不会产生重大影响的错误

有了这三个分类,我们来一个一个看

崩溃型错误
  • 系统调用崩溃性错误

    这种错误一般是程序为了避免进一步的不确定行为和数据损坏,而提前退出

    如 数组越界

    a := []int{
         1, 2, 3}
    fmt.Println(a[3])
    

    运行会直接panic

    panic: runtime error: index out of range [3] with length 3
    
    goroutine 1 [running]:
    main.main()
            /data/www/hello/main.go:12 +0x1b
    exit status 2
    
  • 程序限制型

    net/http包的server.go 有段代码

    func checkWriteHeaderCode(code int) {
         
    	if code < 100 || code > 999 {
         
    		panic(fmt.Sprintf("invalid WriteHeader code %v", code))
    	}
    }
    

    原话是:

    // We used to send "HTTP/1.1 000 0" on the wire in responses but there's
    // no equivalent bogus thing we can realistically send in HTTP/2,
    // so we'll consistently panic instead and help people find their bugs
    // early. (We can't return an error from WriteHeader even if we wanted to.)
    我们过去常常在网络上发送“HTTP/1.1 000 0”作为响应,但现在。
    我们不能在HTTP/2中实际发送等同的虚假信息,
    因此,我们将持续恐慌,帮助人们及早发现他们的缺陷。(即使我们想从WriteHeader返回错误,也不能这样做。)
    

    database/sqlsql.go

    func Register(name string, driver driver.Driver) {
         
    	driversMu.Lock()
    	defer driversMu.Unlock()
    	if driver == nil {
         
    		panic("sql: Register driver is nil")
    	}
    	if _, dup := drivers[name]

相关推荐

  1. 深入理解使用go错误处理--实现

    2024-03-20 13:26:02       20 阅读
  2. 深入理解使用go中间件--实现

    2024-03-20 13:26:02       23 阅读
  3. 深入理解使用go配置--实现

    2024-03-20 13:26:02       19 阅读
  4. 深入理解使用go测试--实现

    2024-03-20 13:26:02       19 阅读
  5. 深入理解使用go函数方法--使用

    2024-03-20 13:26:02       19 阅读
  6. 深入理解使用go函数方法--泛型及堆栈

    2024-03-20 13:26:02       16 阅读
  7. Go语言干货系列:错误处理的最佳实践技巧

    2024-03-20 13:26:02       35 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-03-20 13:26:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-03-20 13:26:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-03-20 13:26:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-03-20 13:26:02       18 阅读

热门阅读

  1. 一文解读ISO26262安全标准:技术安全概念TSC

    2024-03-20 13:26:02       26 阅读
  2. MongoDB聚合运算符:$getField

    2024-03-20 13:26:02       20 阅读
  3. Web框架开发-Django-模板继承和静态文件配置

    2024-03-20 13:26:02       20 阅读
  4. Windows 11 安装 Scoop

    2024-03-20 13:26:02       19 阅读
  5. Web框架开发-Django的模板层

    2024-03-20 13:26:02       21 阅读
  6. Python Web开发记录 Day15:Django part9 数据统计

    2024-03-20 13:26:02       16 阅读
  7. 如何动态修改spring中定时任务的调度策略(1)

    2024-03-20 13:26:02       22 阅读
  8. Dockerfile文件解析

    2024-03-20 13:26:02       19 阅读
  9. 杭州小公司面试

    2024-03-20 13:26:02       16 阅读
  10. 游戏客户端面经

    2024-03-20 13:26:02       20 阅读
  11. unity专题(1)背景图片的设置

    2024-03-20 13:26:02       17 阅读