go语言错误处理(一)

简介: go语言错误处理

错误

通过在函数和方法中返回错误对象作为它们的唯一或最后一个返回值——如果返回 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
}


go语言错误处理(二)https://developer.aliyun.com/article/1391522

相关文章
|
18天前
|
存储 Go 索引
go语言中数组和切片
go语言中数组和切片
27 7
|
17天前
|
Go 开发工具
百炼-千问模型通过openai接口构建assistant 等 go语言
由于阿里百炼平台通义千问大模型没有完善的go语言兼容openapi示例,并且官方答复assistant是不兼容openapi sdk的。 实际使用中发现是能够支持的,所以自己写了一个demo test示例,给大家做一个参考。
|
18天前
|
程序员 Go
go语言中结构体(Struct)
go语言中结构体(Struct)
92 71
|
17天前
|
存储 Go 索引
go语言中的数组(Array)
go语言中的数组(Array)
100 67
|
20天前
|
Go 索引
go语言for遍历数组或切片
go语言for遍历数组或切片
90 62
|
22天前
|
并行计算 安全 Go
Go语言中的并发编程:掌握goroutines和channels####
本文深入探讨了Go语言中并发编程的核心概念——goroutine和channel。不同于传统的线程模型,Go通过轻量级的goroutine和通信机制channel,实现了高效的并发处理。我们将从基础概念开始,逐步深入到实际应用案例,揭示如何在Go语言中优雅地实现并发控制和数据同步。 ####
|
18天前
|
存储 Go
go语言中映射
go语言中映射
32 11
|
20天前
|
Go
go语言for遍历映射(map)
go语言for遍历映射(map)
30 12
|
19天前
|
Go 索引
go语言使用索引遍历
go语言使用索引遍历
27 9
|
23天前
|
安全 Serverless Go
Go语言中的并发编程:深入理解与实践####
本文旨在为读者提供一个关于Go语言并发编程的全面指南。我们将从并发的基本概念讲起,逐步深入到Go语言特有的goroutine和channel机制,探讨它们如何简化多线程编程的复杂性。通过实例演示和代码分析,本文将揭示Go语言在处理并发任务时的优势,以及如何在实际项目中高效利用这些特性来提升性能和响应速度。无论你是Go语言的初学者还是有一定经验的开发者,本文都将为你提供有价值的见解和实用的技巧。 ####