异常处理
一、error
Go语言内置了一个简单的错误接口作为一种错误处理机制,接口定义如下:
type error interface {
Error() string //包含了一个Error()方法,返回值为string
}
error构造:1.error.New()
err := errors.New("This is an error")
if err != nil {
fmt.Print(err)
}
error构造:2.fmt.Errorf()
err := fmt.Errorf("This is an error")
if err != nil {
fmt.Print(err)
}
error构造:3.自定义错误,eg:使用自然数函数
type NotNature float64
func (err NotNature) Error() string {
return fmt.Sprintf("自然数为大于或等于0的数: %v", float64(err))
}
func Nature(x float64) (float64,error) {
if x<0 {
return 0,NotNature(x)
} else {
return x,nil
}
}
func main() {
fmt.Println(Nature(1))
fmt.Println(Nature(-1))
}
示例:1.如果函数需要处理异常,通常将error作为多值返回的最后一个值,返回的error值为nil则表示无异常,非nil则是有异常。
2.一般先用if语句处理error!=nil,正常逻辑放if后面。
Go语言的error代表的并不是真“异常”,只是通过返回error来表示错误信息,换句话说,不是运行时错误范围预定义的错误,某种不符合期望的行为并不会导致程序无法运行(自然数函数例子),都应使用error进行异常处理。当程序出现重大错误,如数组越界,才会将其当成真正的异常,并用panic来处理。
二、panic
Go使用panic和recover来处理异常
package main
import "fmt"
func main(){
defer func(){
fmt.Println("我是defer里面第一个打印函数")
if err:=recover();err!=nil{
fmt.Println(err)
}
fmt.Println("我是defer里面第二个打印函数")
}()
f()
}
func f(){
fmt.Println("1")
panic("我是panic") //程序一开始运行输出1,之后遇到panic跳转到defer函数,defer里的err就是panic中的内容
fmt.Println("2")
}
func main() {
fmt.Println("Hello,Go!")
panic(errors.New(" i am a error"))
fmt.Println("hello,again!")
}
注意:defer和recover定义必须在panic之前,否则无效
panic定义:func panic(v interface{})
recover定义:func recover() interface{}
三、源码分析
errors.New的定义如下:
// src/errors/errors.go
// New returns an error that formats as the given text.
// Each call to New returns a distinct error value even if the text is identical.
func New(text string) error {
return &errorString{text} //new函数返回格式为给定文本的错误,即使文本相同每次对new调用都会返回一个不同的错误值。
}
// errorString is a trivial implementation of error.
type errorString struct {
s string
}
func (e *errorString) Error() string {
return e.s
}