浅谈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中,那么这个错误就会被忽略,可能导致问题的难以追踪和修复。

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

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

相关推荐
脏脏a10 小时前
飞牛NAS部署EasyNVR实操:摄像头RTSP接入、本地录像与公网回看
开发语言·php
杰佛史彦明110 小时前
PDF 表格转 CSV:Python 实现方法与代码解析
开发语言·python·pdf
gugucoding10 小时前
39. 【C语言】经典 C 项目实战:迷你 HTTP 服务器
c语言·开发语言·http
什巳10 小时前
JAVA练习277- 找到字符串中所有字母异位
java·开发语言·算法·leetcode
程序员爱钓鱼10 小时前
Rust 项目目录结构详解:从 Hello World 到企业级项目
后端·rust
岁月宁静11 小时前
DeepSeek Harness 团队 招聘 :JD反推:新手如何系统掌握AI Agent开发技术?
前端·人工智能·后端
灯澜忆梦11 小时前
Go 工程管理与作用域
golang
头茬韭菜11 小时前
3.6 依赖注入 — 四个依赖的精准边界
开发语言·ai·ecmascript
江华森11 小时前
Python神经网络编程(四):Python从零搭建神经网络
开发语言·python·神经网络
编程(变成)小辣鸡12 小时前
如何防止接口被恶意刷?
java·后端·网络安全