
Golang 错误处理与 Defer
错误处理
错误类型(error)
error 在 Go 中是基础类型,以下代码是 error 在 Go 中的定义。只要实现了这个接口就是 error 类型。
type error interface {
Error() string
}
标准库的 errors 包中实现了这个接口,在任何时候,当需要一个错误类型对象时,都可以用 errors 包的 errors.New() 方法接收合适的错误信息来创建。
Panic
在 Go 中,执行错误会触发运行时异常,相当于使用实现了接口类型 runtime.Error 调用内置函数 panic() 。运行时异常用来表示非常严重的不可恢复的错误。
一般不要随意使用 panic() 来终止程序,必须全力补救异常和错误以便让程序能继续执行。
在自定义包中需要做好错误处理和异常处理。
- 在包内部,应该用 recover() 对运行时的异常进行捕获。
- 向包的调用者返回错误值(而不是直接发出异常)。
recover() 的调用仅当它在 defer 修饰的函数中被直接调用时才有效。
Recover
recover() 内建函数用于从异常或错误场景中恢复,让程序可以从异常中重新获得控制权,停止中止过程进而恢复正常执行。
recover() 函数只能在 defer 修饰的函数中使用,用于取得异常传递过来的错误值。如果是正常执行,调用 recover() 函数会返回 nil,且没有其他效果。如果异常传递过来的是 nil 值,则 recover() 函数返回的值也是 nil,所以异常时的参数值不使用 nil。
关于 Defer
Defer 的三个规则
- defer 声明时,其后面函数参数会被实时解析。
package main
import (
. "fmt"
)
func main() {
i := 1
defer Println("result1 =>", func() int {
return i * 2
}())
i ++
defer func() {
Println("result2 =>", i * 2)
}()
i ++
}
程序输出
result2 => 6
result1 => 2
- defer 执行顺序为先进后出(FILO)。
package main
import (]
. "fmt"
)
func main() {
defer Println("!!!")
defer Println("world")
defer Println("hello")
}
程序输出
hello
world
!!!
- defer 可以读取函数的有名返回值。
package main
import (
. "fmt"
)
func func1() (i int) {
defer func() {
i += 10
}()
return 0
}
func main() {
Println("result =>", func1())
}
程序输出
result => 10
这是由于在 Go 中,return 语句不是原子操作,最先是所有返回值在进入函数时都会初始化为其类型的零值,退出返回时先给返回值赋值,然后执行 defer 语句,最后才是 return 操作。