go语言错误处理

go test单元测试 go test是go内置的测试工具 比如现在main.go里有一个方法 func double(num int) int { return num * 2 } 编写测试文件main_test.go package main import ( "testing" ) func TestDouble(t *testing.T) { foo := 1 doubleFoo := double... 阅读详情

错误

通过在函数和方法中返回错误对象作为它们的唯一或最后一个返回值——如果返回 nil,则没有错误发生——并且主调(calling)函数总是应该检查收到的错误。

处理错误并且在函数发生错误的地方给用户返回错误信息:照这样处理就算真的出了问题,你的程序也能继续运行并且通知给用户。 panic and recover 是用来处理真正的异常
库函数通常必须返回某种错误提示给主调(calling)函数。

为了防止发生错误时正在执行的函数(如果有必要的话甚至会是整个程序)被中止,在调用函数后必须检查错误。

if value, err := pack1.Func1(param1); err != nil {
fmt.Printf(“Error %s in pack1.Func1 with parameter %v”, err.Error(), param1)
return // or: return err
}
// Process(value)

错误处理

Go 有一个预先定义的 error 接口类型

type error interface {
Error() string
}

错误值用来表示异常状态;
程序处于错误状态时可以用 os.Exit(1) 来中止运行。

定义错误

任何时候当你需要一个新的错误类型,都可以用 errors (必须先 import)包的errors.New 函数接收合适的错误信息来创建,像下面这样:err := errors.New(“math - square root of negative number”)在下面中你可以看到一个简单的用例:

// errors.go
package main
import (
"errors"
"fmt"
)
var errNotFound error = errors.New("Not found error")
func main() {
fmt.Printf("error: %v", errNotFound)
}
// error: Not found error

可以把它用于计算平方根函数的参数测试:

func Sqrt(f float64) (float64, error) {
if f < 0 {
return 0, errors.New (“math - square root of negative number”)
}
// implementation of Sqrt
}

你可以像下面这样调用 Sqrt 函数:

if f, err := Sqrt(-1); err != nil {
fmt.Printf(“Error: %s\n”, err)
}
```## 用 fmt 创建错误对象
通常你想要返回包含错误参数的更有信息量的字符串,例如:可以用 fmt.Errorf() 来实现:它和fmt.Printf() 完全一样,接收有一个或多个格式占位符的格式化字符串和相应数量的占位变量。和打印信息不同的是它用信息生成错误对象。
比如在前面的平方根例子中使用:
```go
if f < 0 {
return 0, fmt.Errorf(“math: square root of negative number %g”, f)
}

第二个例子:从命令行读取输入时,如果加了 help 标志,我们可以用有用的信息产生一个错误:

if len(os.Args) > 1 && (os.Args[1] == “-h” || os.Args[1] == “--help”) {
err = fmt.Errorf(“usage: %s infile.txt outfile.txt”, filepath.Base(os.Args[0]))
return
}

运行时异常和 panic

当发生像数组下标越界或类型断言失败这样的运行错误时,Go 运行时会触发运行时 panic,伴随着程序的崩溃抛出一个 runtime.Error 接口类型的值。这个错误值有个 RuntimeError() 方法用于区别普通错误。

panic 可以直接从代码初始化:当错误条件(我们所测试的代码)很严苛且不可恢复,程序不能继续运行时,可以使用 panic 函数产生一个中止程序的运行时错误。 panic 接收一个做任意类型的参数,通常是字符串,在程序死亡时被打印出来。Go 运行时负责中止程序并给出调试信息。

package main
import "fmt"
func main() {
fmt.Println("Starting the program")
panic("A severe error occurred: stopping the program!")
fmt.Println("Ending the program")
}

输出如下:

Starting the program
panic: A severe error occurred: stopping the program!
panic PC=0x4f3038
runtime.panic+0x99 /go/src/pkg/runtime/proc.c:1032
runtime.panic(0x442938, 0x4f08e8)
main.main+0xa5 E:/Go/GoBoek/code examples/chapter 13/panic.go:8
main.main()
runtime.mainstart+0xf 386/asm.s:84
runtime.mainstart()
runtime.goexit /go/src/pkg/runtime/proc.c:148
runtime.goexit()
---- Error run E:/Go/GoBoek/code examples/chapter 13/panic.exe with code Crashed
---- Program exited with code -1073741783

一个检查程序是否被已知用户启动的具体例子:

var user = os.Getenv(“USER”)
func check() {
if user == “” {
panic(“Unknown user: no value for $USER”)
}
}

可以在导入包的 init() 函数中检查这些。
当发生错误必须中止程序时, panic 可以用于错误处理模式:

if err != nil {
panic(“ERROR occurred:” + err.Error())
}

Go panicking:

在多层嵌套的函数调用中调用 panic,可以马上中止当前函数的执行,所有的 defer 语句都会保证执行并把控制权交还给接收到 panic 的函数调用者。这样向上冒泡直到最顶层,并执行(每层的) defer,在栈顶处程序崩溃,并在命令行中用传给 panic 的值报告错误情况:这个终止过程就是 panicking。

从 panic 中恢复(Recover)

正如名字一样,这个(recover)内建函数被用于从 panic 或 错误场景中恢复:让程序可以从 panicking重新获得控制权,停止终止过程进而恢复正常执行。

recover 只能在 defer 修饰的函数中使用:用于取得 panic 调用中传递过来的错误值,如果是正常执行,调用 recover 会返回 nil,且没有其它效果。

总结:panic 会导致栈被展开直到 defer 修饰的 recover() 被调用或者程序中止。下面例子中的 protect 函数调用函数参数 g 来保护调用者防止从 g 中抛出的运行时 panic,并展示 panic中的信息:

func protect(g func()) {
defer func() {
log.Println(“done”)
// Println executes normally even if there is a panic
if err := recover(); err != nil {
log.Printf(“run time panic: %v”, err)
}
}()
log.Println(“start”)
g() // possible runtime-error
}

log 包实现了简单的日志功能:默认的 log 对象向标准错误输出中写入并打印每条日志信息的日期和时间。除了 Println 和 Printf 函数,其它的致命性函数都会在写完日志信息后调用 os.Exit(1),那些退出函数也是如此。而 Panic 效果的函数会在写完日志信息后调用 panic;可以在程序必须中止或发生了临界错误时使用它们.下面展示 panic,defer 和 recover 怎么结合使用的完整例子:

// panic_recover.go
package main
import (
"fmt"
)
func badCall() {
panic("bad end")
}
func test() {
defer func() {
if e := recover(); e != nil {
fmt.Printf("Panicing %s\r\n", e)
}
}()
badCall()
fmt.Printf("After bad call\r\n") // <-- wordt niet bereikt
}
func main() {
fmt.Printf("Calling test\r\n")
test()
fmt.Printf("Test completed\r\n")
}

输出:
Calling test
Panicing bad end
Test completed

defer-panic-recover 在某种意义上也是一种像 if , for 这样的控制流机制。

自定义包中的错误处理和 panicking

这是所有自定义包实现者应该遵守的最佳实践:
1)在包内部,总是应该从 panic 中 recover:不允许显式的超出包范围的 panic()。
2)向包的调用者返回错误值(而不是 panic)。
在包内部,特别是在非导出函数中有很深层次的嵌套调用时,对主调函数来说用 panic 来表示应该被翻译成错误的错误场景是很有用的。

// parse.go
package parse
import (
"fmt"
"strings"
"strconv"
)
// ParseError 表示将单词转换为整数时出错。
type ParseError struct {
Index int // 以空格分隔的单词列表的索引。
Word string // 生成分析错误的单词。
Err error // 引发此错误的原始错误(如果有)。
}
// 
func (e *ParseError) String() string {
return fmt.Sprintf("pkg parse: error parsing %q as int", e.Word)
}
// Parse 将 put 中以空格分隔的单词解析为整数。
func Parse(input string) (numbers []int, err error) {
defer func() {
if r := recover(); r != nil {
var ok bool
err, ok = r.(error)
if !ok {
err = fmt.Errorf("pkg: %v", r)
}
}
}()
fields := strings.Fields(input)
numbers = fields2numbers(fields)
return
}
func fields2numbers(fields []string) (numbers []int) {
if len(fields) == 0 {
panic("no words to parse")
}
for idx, field := range fields {
num, err := strconv.Atoi(field)
if err != nil {
panic(&ParseError{idx, field, err})
}
numbers = append(numbers, num)
}
return
}
// panic_package.go
package main
import (
"fmt"
"./parse/parse"
)
func main() {
var examples = []string{
"1 2 3 4 5",
"100 50 25 12.5 6.25",
"2 + 2 = 4",
"1st class",
"",
}
for _, ex := range examples {
fmt.Printf("Parsing %q:\n ", ex)
nums, err := parse.Parse(ex)
if err != nil {
fmt.Println(err) 
continue
}
fmt.Println(nums)
}
}

输出:
Parsing “1 2 3 4 5”:
[1 2 3 4 5]
Parsing “100 50 25 12.5 6.25”:
pkg parse: error parsing “12.5” as int
Parsing “2 + 2 = 4”:
pkg parse: error parsing “+” as int
Parsing “1st class”:
pkg parse: error parsing “1st” as int
Parsing “”:
pkg: no words to parse

一种用闭包处理错误的模式

每当函数返回时,我们应该检查是否有错误发生:但是这会导致重复乏味的代码。结合
defer/panic/recover 机制和闭包可以得到一个我们马上要讨论的更加优雅的模式。不过这个模式只有当所有的函数都是同一种签名时可用,这样就有相当大的限制。一个很好的使用它的例子是 web 应用,所有的处理函数都是下面这样:

func handler1(w http.ResponseWriter, r *http.Request) { ... }

假设所有的函数都有这样的签名:

func f(a type1, b type2)

参数的数量和类型是不相关的。

我们给这个类型一个名字:

fType1 = func f(a type1, b type2)

在我们的模式中使用了两个帮助函数:
1)check:这是用来检查是否有错误和 panic 发生的函数:func check(err error) { if err != nil { panic(err) } }

2)errorhandler:这是一个包装函数。接收一个 fType1 类型的函数 fn 并返回一个调用 fn 的函数。里面就包含有 defer/recover 机制。

func errorHandler(fn fType1) fType1 {
return func(a type1, b type2) {
defer func() {
if e, ok := recover().(error); ok {
log.Printf(“run time panic: %v”, err)
}
}()
fn(a, b)
}
}

当错误发生时会 recover 并打印在日志中;除了简单的打印,应用也可以用 template 包为用户生成自定义的输出。check() 函数会在所有的被调函数中调用,像这样:

func f1(a type1, b type2) {
...
f, _, err := // call function/method
check(err)
t, err := // call function/method
check(err)
_, err2 := // call function/method
check(err2)
...
}

通过这种机制,所有的错误都会被 recover,并且调用函数后的错误检查代码也被简化为调用 check(err)即可。在这种模式下,不同的错误处理必须对应不同的函数类型;

go语言中的错误处理详解 go语言的错误处理机制 阅读详情

相关推荐

Go 语言的错误处理

Go 语言允许你创建自定义错误类型,以便在错误发生时提供更多的信息。自定义错误类型通常是实现了Error()方法的结构体。= nil {在这个例子中,我们创建了一个FileError结构体来封装文件错误信息。这样做的好处是,你可以在错误处理时获取到更多的上下文信息,帮助定位问题。Go 语言的错误处理方式通过显式返回错误值,使得代码更加透明和易于理解。错误处理是 Go 编程中的一个重要部分,理解并掌握它将帮助你编写健壮、可维护的程序。

weixin_52088134的博客 958

Go-知识测试-工作机制

在 Go 语言的源码中,go test 命令的实现主要在 src/cmd/go/internal/test 包中。当你运行 go test 命令时,Go 的命令行工具会调用这个包中的代码来执行测试。在 src/cmd/go/internal/test 包中,runTest 函数是 go test 命令的主要入口点。这个函数负责解析命令行参数,构建测试的二进制文件,启动这个二进制文件,以及读取和解析测试结果。

a18792721831的博客 1832

AutoCAD 2024 Mac版安装激活教程:从下载到破解一站式解决方案

本文提供AutoCAD 2024 Mac版的详细安装与优化指南,包括系统要求检查、下载安装流程、常见问题解决方案及性能优化设置。特别介绍了如何应用最新补丁和Update保持软件性能,帮助用户顺利完成从安装到破解的全过程。

weixin_29239661的博客 851

Go-知识测试-单元测试

单元测试是指对软件中的最小可测试单元进行检查和验证,比如对一个函数的测试。单元测试要保证测试文件以_test.go结尾。测试方法必须以TestXxx开头。测试文件可以与源码处于同一目录,也可以处于单独的目录。

a18792721831的博客 1654

MTK-AWB 小结 (二)

调试总结:可以将offset 对应的ratio加大,保留更多的喜好色(偏色),影响WF statistic gain,从而影响最终的awb gain。这一部分前期CCT校准的时候就会算出一组默认值,当然这个offset offse 值用于优化T,S,wf 光下的偏色喜好度. offset。后面遇到 A H Shad 光收白或者偏色,还可以优化 A 的offset ,H offset,shad offset.new offset 计算过程(Day locus offset 和M/G offset )

qq_46056347的博客 1170

windows搭建IIS(FTP)

适用于参加网络系统管理的学生进行学习与参考

a1119619789的博客 281

Go 语言踩坑记——panic 与 recover

题记 Go 语言自发布以来,一直以高性能、高并发著称。因为标准库提供了 http 包,即使刚学不久的程序员,也能轻松写出 http 服务程序。 不过,任何事情都有两面性。一门语言,有它值得骄傲的优点,也必定隐藏了不少坑。新手若不知道这些坑,很容易就会掉进坑里。《 Go 语言踩坑记》系列博文将以 Go 语言中的 panic 与 recover 开头,给大家介绍笔者踩过的各种坑,以及填坑方法。 初识 panic 和 recover panic panic 这个词,在英语中具有恐慌、恐慌的等意思。从字面意思理

爱生活,爱编程 1749

AXI-5.6 Multiple region interfaces

规则:如果从设备实现的区域少于16个,它必须确保对任何访问未支持区域的尝试都能给出符合协议的响应。具体实现方式由设计者定义。场景:一个错误的软件驱动试图向区域 5(该加密加速器未实现)写入数据。实现方式一:提供错误响应(严格模式)行为:加密加速器检测到AxREGION的值大于2,立即对该事务返回一个DECERR(解码错误)或SLVERR(从设备错误)响应。举例:这类似于你访问一个不存在的网站,服务器返回“404 Not Found”。它明确告知请求者:“你要找的东西不存在”。优点安全、清晰。

weixin_44700185的博客 672

Go testing.common公共类源码剖析

为什么80%的码农都做不了架构师?>>> ...

weixin_34311757的博客 447

QtQuick QML教程(2):qml语法介绍

​ qml一个普通的文本文件,后缀是.qml, 一个qml文件主要由两部分组成:(1) import语句 :这个就像C++中的头文件, 使用 import 导入qml需要的相关模块,可以查询Qt文档进行导入,注意每个版本的Qt模块声明可能都不同,相比于QWidget项目,QtQuick的变动是很大的;(2) QML对象树 :根对象是Window, 然后可以在Window中添加各种控件,例如按钮,文本,菜单等。

琅嬛福地 551

大模型系列——Ollama-OCR 简明教程

Llama 3.2-Vision 是一个多模态大型语言模型,有 11B 和 90B 两种大小,能够处理文本和图像输入以生成文本输出。该模型在视觉识别、图像推理、图像描述和回答与图像相关的问题方面表现出色,在多个行业基准测试中优于现有的开源和闭源多模态模型。在本文中,我将介绍如何调用由 Ollama 运行的 Llama 3.2-Vision 11B 建模服务并使用实现图像文本识别 (OCR) 功能。

2401_84052244的博客 1万+

【Golang学习之旅】Go 语言错误处理(error 接口、panic、recover)

✅ 适合人群:Golang 开发者 | 后端开发工程师 | 并发编程初学者✅ 文章亮点:深入解析 error、panic、recover + 代码示例 + 实战场景✅ 目标:掌握 Go 语言错误处理机制,编写健壮、高质量的 Go 代码!error🔹 Go 语言错误处理的基本原则:✅ 普通错误使用error处理(推荐方式)✅ 严重错误使用panic处理✅ 程序应尽可能优雅地恢复panic用于表示程序发生严重错误,无法继续执行,通常用于不可恢复的错误,如:✅ 数组越界✅ 空指针引用。

程序员林北北的博客 1278

小波变换完全指南:从原理到实践的深度解析

在信号处理领域,傅里叶变换长期以来一直是频域分析的主要工具。然而,傅里叶变换存在一个根本性的局限:它只能告诉我们信号中包含哪些频率成分,却无法告诉我们这些频率成分在什么时刻出现。这就像是你知道一首歌用了哪些音符,却不知道这些音符的演奏顺序。小波变换(Wavelet Transform) 应运而生,它完美地解决了这个问题。小波变换不仅能够提供频率信息,还能同时提供时间信息,实现了信号的时频联合分析。本文将带你从零开始,深入理解小波变换的原理、实现和应用。傅里叶变换的定义如下: 它使用正弦和余弦这样的全局基函数

电脑管家 214

17 go语言(golang) - 错误处理

error使用errors.New或创建简单的文本描述性错误。err1 := errors.New("自定义错误1")err2 := fmt.Errorf("自定义错误2")输出自定义错误1自定义错误2如果需要更复杂或结构化的信息,可以定义自己的类型并实现Error()方法。code intmsg string404,"自定义错误!",输出code:404,msg:自定义错误!{404 自定义错误!

瑞瑞的博客 1190

运维简历优化指南,DeepSeek助您运维简历秒变高分!

例如,当掌握了新的运维技术,如 Serverless 架构的运维管理,就将其添加到简历的专业技能部分,并简要描述在相关项目中的应用情况和成果,如 “在 [项目名称] 中,负责 Serverless 架构的运维工作,成功实现了应用的低成本、高弹性运行,降低了运维成本 30%”。上传简历至 DeepSeek,并输入指令:“请根据以下岗位招聘要求,帮我重新解构我的简历,按照【教育背景→实习经历→项目经历→个人评价→技能证书】的模块,输出一份符合下述岗位的简历,提升我的求职竞争力。

大模型大数据攻城狮的专栏 1471

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

Go语言 错误处理

Go语言 错误处理

代码改变世界 1771

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

100天精通Golang(基础入门篇)——第23天:错误处理的艺术: Go语言实战指南

错误通常指的是预期可能会出现问题的地方确实出现了问题。例如,当尝试打开一个文件失败时,这种情况通常是可以预料到的。异常则是指在不应出现问题的地方却出现了问题。例如,发生了空指针引用,这种情况通常是出乎人们的意料之外的。从这可以看出,错误通常是业务过程的一部分,而异常则不是。创建自定义错误可以使用errors包下的New()函数,以及fmt包下的:Errorf()函数。//errors包://fmt包:在使用New()函数创建自定义错误之前,让我们了解它是如何实现的。下面提供了错误包中的新功能的实现。

猫头虎技术团队:授渔优于赠鱼,兴趣引领智慧,探索之乐尤显珍贵。商务合作+:Libin9iOak ,万粉变现+:优快云WF,猫头虎承诺每年免费为100名C站创作者做账号流量诊断服务!全网搜:猫头虎技术团队,点击文章底部名片或直接私信我一切皆可谈,快找虎哥! 5万+

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

翻译golang的一篇文章-Go 语言的错误处理

我翻译的关于go语言错误处理的文章 原文地址 译文地址

aslucky的专栏 639

Go语言错误处理

Go语言错误处理

YIYIYI 2022

Go语言中的错误处理

/ ...显式优于隐式:错误必须明确检查简单可预测:没有隐藏的控制流错误即值:错误是普通的值,可以传递和组合更清晰的代码流程更可靠的错误处理更好的可调试性掌握Go的错误处理模式是成为优秀Go开发者的关键一步。

言之。 1万+

Go语言的错误处理

当需要携带更多错误信息(如错误码、上下文)时,可以自定义实现errorimport ("fmt"// 自定义错误类型,包含错误码和错误信息Code int // 错误码Msg string // 错误信息// 实现error接口的Error()方法return fmt.Sprintf("错误码:%d,信息:%s", e.Code, e.Msg)// 模拟业务函数返回自定义错误return "", &MyError{Code: 400, Msg: "用户ID不合法"}

shenxiaomo1688的博客 409

golang笔记08--go语言错误处理和资源管理

golang笔记08--go语言错误处理和资源管理1 介绍2 错误处理和资源管理2.1 defer调用2.2 错误处理概念2.3 服务器统一出错处理2.4 panic和recover2.5 服务器统一出错处理23 注意事项4 说明 1 介绍 本文继上文 golang笔记07–go语言函数式编程, 进一步了解 go语言的错误处理和资源管理,以及相应注意事项。 具体包括 : defer调用 、错误处理概念、服务器统一出错处理、panic和recover、服务器统一出错处理2 等内容。 2 错误处理和资源管理 2

脚步不能达到的地方,眼光可以达到;眼光不能达到的地方,精神可以飞到 445

Go语言错误处理详解

Go语言的错误处理机制以error接口为核心,通过返回错误值来处理异常。本文详细介绍了错误处理的基本概念、自定义错误类型、错误包装以及panic和recover的用法。此外,Go 1.13引入了错误包装功能,使得错误链的追踪和处理更加方便。文章还讨论了错误处理的最佳实践,强调了优先返回错误、避免滥用panic、提供有用的错误信息等技巧,以提高代码的健壮性和可维护性。

一个被知识诅咒的人 1362

16.Go 语言错误处理

Go 语言错误处理

chxii的专栏 1514

使用Go语言的错误处理增强库 xerrors 指南

使用Go语言的错误处理增强库 xerrors 指南 项目介绍 xerrors 是 Go 语言中的一个扩展错误处理库,由 Golang 官方维护在 golang.org/x/ 子仓库下。它提供了一种更强大且表达性更强的方式来处理错误,包括但不限于错误包装(error wrapping),以保持错误链的完整性,以及更易于调试的错误信息。这对于追求高效率和代码质量的Go开发者来说,是一个非常实用的工具。...

gitblog_00739的博客 505
上一篇: rust安装 -自定义安装路径和GCC安装
下一篇: go语言中的socket和http
过去日记
过去日记 新星创作者: 后端开发技术领域 新星创作者: 后端开发技术领域
博客等级 码龄3年 5343粉丝 225原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

过去日记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值