1. 异常处理机制
在Golang中,异常处理机制主要由panic和recover构成。
1.1 panic
panic用于向上传递错误信息。当程序执行过程中发生了错误,而且该错误无法被处理时,通常会调用panic函数,程序执行会停止,并且立即执行该goroutine所在的defer语句。
下面是一个简单的示例:
func testPanic() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recovered from:", err)
}
}()
panic("panic happened")
}
func main() {
testPanic()
fmt.Println("program normally exits")
}
运行结果:
recovered from: panic happened
program normally exits
由于程序执行了panic函数,导致程序退出之前执行了defer语句,并且执行了recover函数,输出了错误信息。
1.2 recover
recover用于捕获panic抛出的错误信息,并且使程序恢复正常运行。换句话说,recover可以使goroutine从panic状态恢复过来。它只能在defer语句中调用,并且必须在panic的下一行代码执行,否则recover将无法捕获到错误信息。
下面是一个简单的示例:
func testRecover() {
defer func() {
if err := recover(); err != nil {
fmt.Println("recovered from:", err)
}
}()
panic("panic happened")
fmt.Println("after panic")
}
func main() {
testRecover()
fmt.Println("program normally exits")
}
运行结果:
recovered from: panic happened
program normally exits
由于程序执行了panic函数,导致程序退出之前执行了defer语句,并且执行了recover函数,使得程序恢复了正常运行,输出了程序正常退出的消息。
2. 错误恢复机制
Golang中的错误恢复机制是通过defer和panic+recover组合使用来实现的。通过这种机制,可以将错误信息从运行时逐层传递,直到被捕获并且处理。
2.1 示例:打开和读取文件
下面是一个常见的读取文件的错误处理示例:
func ReadFile(filename string) ([]byte, error) {
f, err := os.Open(filename)
if err != nil {
return nil, err
}
defer f.Close()
buf := make([]byte, 1024)
var result []byte
for {
n, err := f.Read(buf[:])
if err != nil && err != io.EOF {
return nil, err
}
if n == 0 {
break
}
result = append(result, buf[:n]...)
}
return result, nil
}
func main() {
data, err := ReadFile("no_such_file.txt")
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println(string(data))
}
运行结果:
error: open no_such_file.txt: no such file or directory
在上面的示例中,通过defer语句确保文件在读取完成之后被关闭,而且在打开文件的过程中出现错误时,无论在哪里都会向上传递该错误信息,直到被main函数捕获,并且输出错误信息。在这个过程中,程序使用了错误码的方式,不同的错误码代表了不同的错误信息。
2.2 示例:数据库访问
下面是一个数据库访问的错误处理示例:
func queryData() error {
db, err := sql.Open("mysql", "user:password@tcp(127.0.0.1:3306)/mydb")
if err != nil {
return err
}
defer db.Close()
rows, err := db.Query("select * from mytable")
if err != nil {
return err
}
defer rows.Close()
for rows.Next() {
// do something
}
return nil
}
func main() {
err := queryData()
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Println("successful")
}
在上面的示例中,同样使用了defer语句确保资源被回收,并且在出现错误时都向上传递该错误信息,直到被main函数捕获,并且输出错误信息。
3. 总结
Golang通过panic和recover来实现异常处理机制,通过defer和panic+recover组合使用来实现错误恢复机制。在开发过程中,合理利用异常处理和错误恢复机制可以提高程序的稳定性和健壮性。