如果函数实现过程中,如果出现不能处理的错误,可以返回给调⽤者处理。⽐如我们调⽤标准库函数 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
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
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最后,调⽤返回到顶层函数,然后将错误消息和堆栈信息打印出来。
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 recoverSayHirecoverSayHi中的 recover() 捕捉到了这个异常,并停⽌了异常继续向上抛它调⽤了 recover(),并接收到 panic 的错误信息。