来一个除以0的异常,代码如下:
package main
import "fmt"
func main() {
fmt.Println("before")
divNum()
fmt.Println("after")
}
func divNum() {
num1 := 10
num2 := 0
result := num1 / num2
fmt.Println(result)
}
console 异常:
before
panic: runtime error: integer divide by zero
goroutine 1 [running]:
main.divNum()
C:/Users/Lenovo/IdeaProjects/go-helloworld/class02/demo06/main.go:15 +0x11
main.main()
C:/Users/Lenovo/IdeaProjects/go-helloworld/class02/demo06/main.go:8 +0x5b
exit status 2
恐慌: 运行时 整数除以零的恐慌。
before 输出后,遇到恐慌异常,代码运行时,因为错误恐慌中断,后面的代码 after并没有执行出来。常常我们不想程序的代码流就这么在运行时就中断掉,就需要引入一些技术,错误能被捕获并处理掉。
在java中有try...catch...finally 来处理异常,在Go中,为了追求代码的优雅,采用的是defer...recover来处理这里的恐慌panic 。
defer recover 机制处理错误:
defer 前面学过了,但是什么是recover函数?
官方解释及有道翻译:
The recover built-in function allows a program to manage behavior of a panicking goroutine. 内置包的recover函数允许程序管理恐慌goroutine go程序 的行为。
Executing a call to recover inside a deferred function (but not any function called by it) stops the panicking sequence by restoring normal execution and retrieves the error value passed to the call of panic. 在延迟函数(而不是它调用的任何函数)内部执行恢复调用,通过恢复正常执行来停止恐慌序列,并检索传递给panic调用的错误值。
If recover is called outside the deferred function it will not stop a panicking sequence.如果在deferred函数外部调用recover,则不会停止恐慌序列。
In this case, or when the goroutine is not panicking, or if the argument supplied to panic was nil, recover returns nil. Thus the return value from recover reports whether the goroutine is panicking.在这种情况下,或者当goroutine没有panic,或者提供给panic的参数为nil时,recover将返回nil。因此,recover的返回值报告goroutine是否出现异常。
这里,nil是零值,返回nil 则说明 goroutine 有错误。 代码如下:
package main
import "fmt"
func main() {
fmt.Println("before")
divNum()
fmt.Println("after")
}
func divNum() {
//利用defer + recover 捕获错误
// 1.defer 后加一个匿名函数调用。
defer func() {
// 2.匿名函数内开一个局部变量,看 recover返回是 nil 还是错误。。
err := recover()
//3.如果recover 返回的不是零,说明goroutine有错误,打印该错误。
if err != nil {
fmt.Println(err)
}
}()
num1 := 10
num2 := 0
result := num1 / num2
fmt.Println(result)
}
查看 console 输出:
before
runtime error: integer divide by zero
after
Go语言的自定义错误: 由于 runtime error: integer divide by zero 对我们不是很友好,看下Go语言是如何支持自定义错误的。 自定义错误,需要调用errors包瞎的New函数进行操作,函数会返回一个error类型。
package main
import (
"errors"
"fmt"
)
func main() {
fmt.Println("before")
err := divNum()
if err != nil {
fmt.Println(err)
}
fmt.Println("after")
}
func divNum() (err error) {
num1 := 10
num2 := 0
// 抛出自定义错误。
if num2 == 0 {
err := errors.New("除数不能为0")
return err
} else {
result := num1 / num2
fmt.Println(result)
return nil
}
}
上面发生错误,程序正常执行了,有时候,我们希望发生错误,程序停止执行。
panic(err) //抛出异常,停止代码流。相当于java 中的new Exception();
package main
import (
"errors"
"fmt"
)
func main() {
fmt.Println("before")
err := divNum()
if err != nil {
fmt.Println(err)
panic(err) //抛出异常,停止代码流。相当于java 中的new Exception();
}
fmt.Println("after")
}
func divNum() (err error) {
num1 := 10
num2 := 0
// 抛出自定义错误。
if num2 == 0 {
err := errors.New("除数不能为0")
return err
} else {
result := num1 / num2
fmt.Println(result)
return nil
}
}
That's all , next point ...