GO成神之路: Go异常处理(一)|Go主题月

1,241 阅读2分钟

try...catch是软件开发过程中一个很有用的功能,可惜Go中并没有直接提供这样的语法支持,但Go中提供了另外一种语法支持,那就是recover...panic

虽然recover...panictry...catch功能类似,但是编程思想并不一样:

try...catch的编程思想

  1. 防止代码异常退出或崩溃
    try{
        //将文件操作放在try中防止代码异常
        open("file")
    }
    catch(ex){
        log.print(ex)
    }
    finaly{
        //....
    }
    
  2. 快速返回错误信息,防止return返回无意义的值 下面例子中添加一个用户,添加成功后返回用户ID,添加失败时返回错误原因: 在其它高级语言中如果要返回两种类型的参数通常需要定义个聚合结构类型(如:struc或class)
try{
    addUser({"name":"",age:0})
}
catch(ex){
    log.print(ex)
}
finaly{
    //....
}

class Result{
    string err
    int userId
}

func addUser(user) Result {
    if user.name==""{
        return Result{
            err:"用户名为空",
            userId:0
        }
    }
    var userId=save_to_db(user)
    
    return Result{
        err:"",
        userId:123
    }
}

recover...panic的编程思想

这是go中特有编程思想,Go认为所有的函数都应该返回至少1个error值,因为Go支持多返回值。 虽然2021年的今天多返回值的语言越来越多,但是在Go语言诞生哪个年代,几乎没有高级语言支持多返回值,Go当时的语法是相当精简与超前的。

编程思想:代码规范大于一切

所有的函数应该至少包涵一个返回值

func method() error{
    if 存在错误:
        return error("出错了")
    return nil
}

谨慎使用panic返回错误信息

panic是用来结束不符合预期情况的代码继续执行,这点与try...catch并无区别。

通常应该使用panic来结束无法自行修正数据问题的代码片段,如果问题不致命则尽量不要使用panic。

func init() {
    if user == "" {
        // 这段代码摘自官方教程,例子只是例子,按照go创建panic的思想,下列代码应该避免使用
        panic("no value for $USER")
        
        // 正确的使用应该时返回错误
        //return error("no value for $USER")
    }
}

recover...panic只是对error的补充

最初Go中只有error的时候,我们的函数要像下面这样写,看起来冗长丑陋

if err:=a();err!=nil{
}
if err=b();err!=nil{
}
if err=c();err!=nil{
}

当有了panic时,我们的函数可以这样写:

func test(){
    defer func(){
        if err:=recover();err!=nil{
            log.print(err)
        }
    }()
    a()
    b()
    c()
}

我的理解

try...catchrecover...panic无疑时非常相似的,相似到可以理解为一个东西的两种写法,只是发明者赋予他们以上不太一样的设计思路。