浅谈go语言的错误处理

前言

本文是探讨的是"go语言中如何优雅地处理错误"

观察go语言源码

在go语言的内置函数中,很多的函数都会返回一个error,特别是在与文件读写操作的相关的函数的时候,基本上都会有返回error,返回这个的好处是用来辨别是否出错,把结果直接告诉你,以便你进行下一步操作,而不是因为这个报错,就导致直接就退出程序

比如说最简单的Printf函数

其实在后面也是有返回一个error的,但是由于这个函数过于简单,所以我们就不常用而已,就我个人而言,我建议我们自己写代码的时候,如果有比较复杂的操作,也可以进行error的处理,下面是一个简单的示例

go 复制代码
func division(a, b int) (c int, err error) {
   if b == 0 {
      return 0, errors.New("被除数为0")
   }
   c = a / b
   return c, nil
}

os.Exit和panic的差别

最显著的区别就是,panic引发程序终止的话,我们可以在defer关键字标记的延时执行的函数里面,进行后续错误处理,可以让程序继续运行,而os.Exit就会直接终止,不利于我们进行下一步操作

下面是详细的解释:

os.Exit(1)用于无法恢复的错误,它会立即终止程序的运行,并返回给操作系统一个退出状态码。退出状态码1通常用于表示程序发生了错误。os.Exit函数不会打印任何错误信息,因此无法得知具体的错误原因。

go 复制代码
package main

import (
	"fmt"
	"os"
)

func main() {
	// 终止程序的运行,并返回退出状态码1
	fmt.Println("Before os.Exit")
	os.Exit(1)
	fmt.Println("After os.Exit") // 不会执行到这里
}

panic用于表示程序发生了无法处理的错误,它会导致程序崩溃并打印错误信息。panic函数会触发一系列的延迟函数(defer)的执行,然后终止程序的运行。可以使用recover函数来捕获panic并进行处理。

go 复制代码
package main

import (
	"fmt"
)

func main() {
	// 触发panic,程序崩溃
	fmt.Println("Before panic")
	panic("Something went wrong")
	fmt.Println("After panic") // 不会执行到这里
}

总结:

os.Exit(1)用于无法恢复的错误,立即终止程序并返回退出状态码。

panic用于无法处理的错误,导致程序崩溃并打印错误信息。

创造性的错误处理

2015年1月,GO博客发表了一篇关于错误处理的文章"Error are values",该文描述了一种简单处理方法,具体可以看下面的代码

go 复制代码
type safeWriter struct {
    w io.Writer
    err error  // 存储错误的地方
}

func (sw *safeWriter) writer (s string){
    if sw.err != nil {   // 如果前面有错误发生,就直接跳过写入操作
        return   
    }
    
    _,sw.err= fmt.Fprintln(sw.w,s) // 尝试写入文本行并储存可能出现的错误
}

这种错误处理的方法使用了一个自定义的类型safeWriter,其中包含了一个io.Writer接口和一个错误err。在写入操作之前,先检查err是否为空,如果不为空则直接跳过写入操作,避免出现更多错误。在写入操作之后,通过fmt.Fprintln函数尝试写入文本行,并将可能出现的错误存储在err中。

这种错误处理的方法有以下优点:

可以避免错误的连锁反应:如果前面发生了错误,后续的写入操作会被跳过,避免了错误的扩散和更多的错误发生。

错误信息可以被保存:通过将错误信息存储在err中,可以在需要时获取并进行处理,比如将错误信息记录到日志中或者返回给调用者。

然而,这种错误处理的方法也有一些潜在的问题:

可能会忽略某些错误:如果在写入操作之后发生了错误,但是没有将其存储在err中,那么这个错误就会被忽略,可能导致问题的难以追踪和修复。

可能会导致部分写入数据丢失:如果在写入操作之后发生了错误,但是没有进行处理,那么部分数据可能无法成功写入,导致数据丢失。

总的来说,这种错误处理的方法在简单场景下是有效的,可以避免错误的连锁反应,并且可以将错误信息保存下来。但是在复杂的场景下,可能需要更加细致的错误处理机制来确保所有的错误都被处理和记录。

相关推荐
电饭叔30 分钟前
《python语言程序设计》2018版第8章19题几何Rectangle2D类(下)-头疼的几何和数学
开发语言·python
Eternal-Student31 分钟前
everyday_question dq20240731
开发语言·arm开发·php
卑微求AC1 小时前
(C语言贪吃蛇)11.贪吃蛇方向移动和刷新界面一起实现面临的问题
c语言·开发语言
夜月行者1 小时前
如何使用ssm实现基于SSM的宠物服务平台的设计与实现+vue
java·后端·ssm
程序猿小D1 小时前
第二百六十七节 JPA教程 - JPA查询AND条件示例
java·开发语言·前端·数据库·windows·python·jpa
Yvemil71 小时前
RabbitMQ 入门到精通指南
开发语言·后端·ruby
sdg_advance1 小时前
Spring Cloud之OpenFeign的具体实践
后端·spring cloud·openfeign
潘多编程1 小时前
Java中的状态机实现:使用Spring State Machine管理复杂状态流转
java·开发语言·spring
冷静 包容2 小时前
C语言学习之 没有重复项数字的全排列
c语言·开发语言·学习
猿java2 小时前
使用 Kafka面临的挑战
java·后端·kafka