06、GO异常处理

1. 错误处理 (error handling)
如果函数实现过程中,如果出现不能处理的错误,可以返回给调⽤者处理。
⽐如我们调⽤标准库函数 os.Open 读取⽂件
os.Open 2 个返回值,第⼀个是 *File ,第⼆个是 error
如果调⽤成功, error 的值是 nil => nil 是⼀个空值
如果调⽤失败,例如⽂件不存在,将返回⼀个⾮空 error 。我们可以通过 error 知道具体的错误信息。
package main

import "fmt"
import "os"

func main() {
	fmt.Println("vim-go")
	_, err := os.Open("a.txt")
	if err != nil {
		fmt.Println("出错啦")
		fmt.Println(err)
	 }
}
[root@localhost src]# go run error.go 
vim-go
出错啦
open a.txt: no such file or directory

可以通过 errors.New 返回⾃定义的错误

package main

import "fmt"
import "os"
import "errors"
func main() {
	fmt.Println("vim-go")
	_, err := os.Open("a.txt")
	if err != nil {
		fmt.Println("出错啦")
		fmt.Println(err)
	 }
}

func myprint(name string) error {
	if len(name) == 0 {
		return errors.New("error: name is null")

	}
	fmt.Println(name)
	return nil
}
[root@localhost src]# go run error.go 
vim-go
出错啦
open a.txt: no such file or directory
4. defer
defer有延迟的意思,就是稍后执⾏,先执⾏函数主体内容,defer的内容稍后执⾏
主体内容执⾏完毕后,defer的内容按照调⽤顺序的 相反顺序 逐个执⾏defer 的执⾏⽅式类似其他语⾔中的 析构函数 即使函数发⽣ 严重错误 也会执⾏
常⽤于 资源清理、⽂件关闭、解锁以及记录时间 等操作⽀持匿名函数的调⽤通过与匿名函数配合可在return之后 修改 函数计算结果
如果函数体内某个变量作为defer时匿名函数的参数,则在定义defer时即已经获得了拷⻉,否则则是引⽤某个变量的地址

 示例:使用defer关键字

func main() {
 fmt.Println("main_a")
 defer fmt.Println("deffer_a")
 fmt.Println("main_b")
 defer fmt.Println("deffer_b")
 fmt.Println("main_c") }
# go run func.go
main_a
main_b
main_c
deffer_b
deffer_a
5. panic
panic英⽂意思是恐慌,在这⾥意思是抛出⼀个程序异常,即报告程序运⾏时错误
当在⼀个函数执⾏过程中调⽤ panic() 函数时,正常的函数执⾏流程将⽴即终⽌,可以理解为 Throw
之前使⽤ defer 关键字延迟执⾏的语句将正常展开执⾏,并导致逐层向上执⾏ panic 流程
直⾄所属的 goroutine 中所有正在执⾏的函数被终⽌。
错误信息将被报告,包括在调⽤ panic() 函数时传⼊的参数,这个过程称为错误处理流程。
package main
import "fmt"
func main(){
 defer fmt.Println("deferred main")
 sayHi("")
}
func sayHi(name string){
 defer fmt.Println("deferred sayHi")
 if len(name)<1{
 panic("hahaha")
 }
 fmt.Println("hi", name)
 fmt.Println("bla,bla")
}

 输出结果

deferred sayHi
deferred main
panic: hahaha
goroutine 1 [running]:
main.sayHi({0x0?, 0x60?})
 /Users/beebol/golearn/c.go:13 +0x149
main.main()
 /Users/beebol/golearn/c.go:7 +0x74
exit status 2
执⾏过程:
执⾏到 panic("hahaha") 时,程序控制权交给defer
⾸先 sayHi ⽅法中的 defer 被执⾏,输出: deferred sayHi
接着,从 sayHi ⽅法返回到main ⽅法中的 defer 被执⾏,输出: deferred main
最后,调⽤返回到顶层函数,然后将错误消息和堆栈信息打印出来。

 6. recover

recover() 函数⽤于终⽌错误处理流程,也就是我们常规说的 catch。
recover() 应该在⼀个使⽤ defer 关键字的函数中执⾏,以有效截取错误处理流程。
Panic 可以在任何地⽅引发,但 recover 只有在 defer 调⽤的函数中有效
如果没有在发⽣异常的 goroutine 中明确调⽤恢复过程(使⽤ recover 关键字),会导致该 goroutine 所属
的进程打印异常信息后直接退出。

 示例:
 

package main
import "fmt"
func main(){
 sayHi("")
 fmt.Println("end!!")
}
func sayHi(name string){
 arr := []int{1,2,3}
 defer recoverSayHi()
 if len(name)<1{
 fmt.Println(arr[5])
 // panic("hahaha")
 }
 fmt.Println("hi", name)
 fmt.Println("bla,bla")
}
func recoverSayHi(){
 fmt.Println("you can clean")
 if r := recover(); r!=nil{
 fmt.Println("recoved from", r)
 }
}
执⾏过程
调⽤sayHi函数,recoverSayHi() 被延迟执⾏
sayHi中遇到异常/调⽤panic,触发defer recoverSayHi
recoverSayHi中的 recover() 捕捉到了这个异常,并停⽌了异常继续向上抛
它调⽤了 recover(),并接收到 panic 的错误信息。

猜你喜欢

转载自blog.csdn.net/qq_48391148/article/details/126191888