Go语言错误处理(13)|Go主题月

471 阅读3分钟

err != nil

Go语言的错误处理一直被人诟病,也没有try,catch的,跟其他语言相比真的很反人类, Go语言处理错误时通常都是将返回的错误与 nil 比较。nil 值表示了没有错误发生,而非 nil 值表示出现了错误。所以说在经常会出现下面几行代码:

if err != nil {
        fmt.Println("error:",err)
        return
    }

如果自己要实现一个函数,想要把错误信息传递到调用者的话,就要在函数的返回值那里定义一个error类型,这个error 类型实际上是用了 Error() 方法的 error接口,实现该接口的类型都可以当作一个错误类型:

type error interface {  //error接口
    Error() string   //Error方法
}

在很多第三方包方法或者内置包方法都会使用到这个error接口,来一个实际例子:

package main
import (
    "fmt"
    "strconv"
)

func main() {
    resp, err := strconv.Atoi("hello")  //strconv数据类型转换的内置包,Atoi方法是把string转换为int,现在里面是hello无法转为int,所以下面会报错
    if err != nil {
            fmt.Println(err) //输出错误:strconv.Atoi: parsing "hello": invalid syntax
    }else{
            fmt.Println(resp)
    }
}

我们自己写代码也可以使用这个方法,把错误信息传递到调用者,让调用者判断是否有误,如下面所示:

package main
import (
	"fmt"
	"errors"
)

func ErrorMake(a,b int) (int,error){
	if b==0 {
		return 0,errors.New("b不能为零")
	}else {
		return a / b,nil
	}
}
func main() {
	var a,b=1,0
	resp,err := ErrorMake(a,b)
	if err!=nil {
		fmt.Println(err)  //b不能为零
	}else {
		fmt.Println(resp)
	}
}

image.png

panic和defer

panic 单词的意思就是恐慌,在Go语言的作用就是主动抛出错误,我经常使用Python的时候使用raise主动抛出错误,然后给try except接受这个错误,进入错误处理的程序,可以看看Pyhon的代码:

try:
    a = input("输入一个数:")
    if(not a.isdigit()):
        raise ValueError("a 必须是数字")
except ValueError as e:
    print("引发异常:",repr(e))  //输入除数字之外的东西就会主动到这里来输出错误信息

panic呢?主动抛出错误的例子:

package main
import "fmt"

func showpanic(data int){
    if data == 0{
        panic("传入参数为零。不支持哦")
    }else{ 
        fmt.Println(data)
    }
}


func main() {
    showpanic(1)  //输出1
    showpanic(0)  //主动抛出错误 传入参数为零。不支持哦
}

panic 是一个非常严重的错误,会导致程序终止运行,程序终止运行后一般会需要配合释放一些资源,比如关闭文件,关闭网络连接,退出登录等等,在Go语言经常会看到使用panic主动抛出错误可以配合defer使用来实现错误主动抛出,主动接受,defer是什么呢? defer 关键字用于修饰一个函数或者方法,在该函数或者方法在返回前执行,这里有个经常会考的点,多个defer,倒序执行,堆栈一样先进后出,先简单看看defer例子:

package main
import "fmt"

func testdefer(data string)  (return_data string) {
    defer fmt.Println("666")
    return data+"10086"  
}

func main() {
    fmt.Println(testdefer("call "))
}

依次会输出:

666
call 10086

defer 在抛出错误之前,函数或方法return之前都会执行:

package main
import "fmt"

func login(password string)  (return_data string) {
    defer fmt.Println("666")
    return data+"10086"  
}

func main() {
    fmt.Println(testdefer("call "))
}

panic 和defer一起使用:

package main
import "fmt"

func login(password string)  (return_data string) {
    defer fmt.Println("记录")
    
    if (password=="123456"){
        return "登录成功"
    }else{
        panic ("致命错误,GG")
    }
}
func main() {
    fmt.Println(login("123456"))
    fmt.Println(login("654321"))
}

输出:

记录
登录成功
记录
panic: 致命错误,GG
....

这个panic 关键字一般是是不推荐使用的,因为使用它代表了程序的终止运行,一般使用error,error抛出错误是不会终止程序的。

image.png