Golang Go语言中错误如何处理

发布于 1周前 作者 eggper 来自 Go语言
楼主编程业余爱好者,用的最多的是 JS
一直想学一款编译型语言,写了几天 Go
虽然功能能实现 但是在错误处理方面感觉弄的很差
编码方式基本是写小函数然后组成中函数再组成大函数
这种编程方式不知道叫什么,使用 go 的话应该学习什么编程方式?
在体验的这几天里 最难搞的就是错误处理了
第一次接触这类的错误处理方式
好像是说每个可能出错的函数需要返回 error 或 nil
于是我给可能出错的小函数添加了 error 返回值
于是在中函数里调用这些小函数是不是也需要返回这个 error
然后大函数里调用到会返回 error 的中函数就需要返回 error 层层传递叠加
不知道我有没有解释清楚

Golang Go语言中错误如何处理

更多关于Golang Go语言中错误如何处理的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html

26 回复

看你当前层需不需要处理这个错误,需要对特定错误做处理的时候就用 is/as 之类的做判断

更多关于Golang Go语言中错误如何处理的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


需要处理就就地处理,不需要处理的就上抛。如果你觉得没有需要你处理的错误。。
看实际情况吧,举个例子,web 服务,如果业务一路上抛错误,那么到 web server 的 handler 上,它会统一把这个错误处理成 500 Server error ,至于错误内的 stack 信息,完全取决于你自己实现。

是的,跟 c 一样,不过 c 一般返回的 int

你说的编程方式是自底向上。
你说的小函数增加错误返回,中函数大函数也要改,没错。没什么办法,习惯就好了。有经验以后你一开始就会给中函数加上错误返回的签名。

难道 js 不是这样做的吗?

Go 提供了机会给你认真对待每一个错误,严格来说确实应该认真对待,这样晚上睡觉也踏实一点。

但是初学者用 panic 偷懒我觉得也没啥问题。用 panic 就不用层层传递了,直接崩。

go 只能这么处理,准确来说 go 没有设计错误处理机制,被社区内外无数人诟病。不过也有人喜欢这种原始写法就是了。另外 go 的 err 没有堆栈

“编码方式基本是写小函数然后组成中函数再组成大函数”

实际上不仅仅是编程,这是人类解决各种复杂问题的通用方法,十分有效,可以了解一下其原理,思考和开发效率会更高: https://www.modevol.com/episode/cl4zh80o48f2101o3e2iv849s

可以参考大多数 Java 程序员的处理方式,吃掉错误,继续运行

基本就是层层返回,如果想比较清晰定位错误,就在返回的时候携带一些信息,或者打日志

谢谢各位 原来我大致的方向已经是正确的
看来只能接受繁琐的错误层层传递
js 转来感觉 1/3 的时间在写 error
1/3 在写 struct

差不多,错误处理被诟病的一大原因就是大量的时间花在了 if err != nil 上了

大道至简🐶

你想想 c 语言的,只能返回值呢

if err != nil 当成 try catch 呗

这是逼迫你更细致的处理错误,在使用异常的语言中,如果要细致处理错误,代码量并不比 Go 这样的小。

Go 的错误处理思想继承自 C ,有点“程序的性能消耗和代码量成正比”的意思。比如错误不自带堆栈,因为堆栈有性能开销,如果确实需要的话程序员就要手动加,手动加的时候还可以加上更多上下文信息,有时候比异常更好。

个人认为应该将错误分成两类:意料之外的,属于程序 bug 的,直接 panic ;意料之内的用户输入错误,上游 API 错误,用 error 处理。

推荐看看这篇 The Error Model: https://joeduffyblog.com/2016/02/07/the-error-model/

经常有人吐槽 go 这个设计,隔一段时间就能碰见

go 社区刚刚拒绝了所有关于新增错误处理特性的提案



凑合过呗, 还能离咋地

个人还是比较喜欢 go 这种错误处理方式的。时刻提醒自己,你写的每行代码都可能出错,就不会有“小函数增加错误返回,中函数大函数也要改”这种情况了

这代码写的一半是 err 判断的感觉
···go
func GetFileName(hash string, sid string) (string, error) {
apiUrl := Url + “/api/v2/torrents/files”
data := url.Values{}
data.Add(“hash”, hash)
req, err := http.NewRequest(“POST”, apiUrl, strings.NewReader(data.Encode()))
if err != nil {
return “”, fmt.Errorf(“创建请求失败: %w”, err)
}
req.Header.Set(“Content-Type”, “application/x-www-form-urlencoded”)
req.Header.Set(“Cookie”, “SID=”+sid)

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
return “”, fmt.Errorf(“请求失败: %w”, err)
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return “”, fmt.Errorf(“服务器返回错误状态码: %d”, resp.StatusCode)
}

body, err := io.ReadAll(resp.Body)
if err != nil {
return “”, fmt.Errorf(“读取响应体失败: %w”, err)
}

var data []Data
if err := json.Unmarshal(body, &data); err != nil {
return “”, fmt.Errorf(“解析 JSON 失败: %w”, err)
}

if len(data) == 0 {
return “”, fmt.Errorf(“未找到文件数据”)
}

return data[0].Name, nil
}
···

一个函数内写了 5 个 err 判断,前期真的很麻烦,后期 debug 是真方便。。。

这可是 errlang ,别挣扎了 /doge

使用 Github copilot 相关 AI 工具,让它帮你写,要求它处理所有错误。

写点小代码我直接 panic……

在Golang(Go语言)中,错误处理是一个非常重要的方面,其设计哲学鼓励显式地处理可能出现的错误情况。以下是Go语言中错误处理的一些关键点:

  1. 错误类型:在Go中,错误是一个内置接口类型,任何实现了Error()方法的类型都可以作为错误类型。这通常通过定义一个类型并实现error接口来完成。

  2. 返回错误:Go函数通常通过返回两个值(通常是最后一个值为错误类型)来处理错误。这种方式允许调用者检查并处理错误。

  3. 错误检查:调用函数后,应立即检查错误值是否为nil。如果不是,应采取适当的错误处理措施,如记录日志、清理资源或向用户报告错误。

  4. panic与recover:对于编程错误或无法恢复的错误情况,Go提供了panic机制。这会导致程序中断执行,并可以通过recover函数在延迟(defer)函数中捕获,以恢复程序的正常运行。但应谨慎使用,因为过度使用panicrecover可能会使代码难以理解和维护。

  5. 自定义错误:通过定义自己的错误类型,可以提供更丰富的错误信息,如错误码、错误描述等,使错误处理更加灵活和强大。

总之,Go语言的错误处理机制鼓励程序员显式地处理错误,通过返回错误值、检查错误并采取适当的措施,来确保程序的健壮性和可靠性。

回到顶部