大家好,我是煎鱼。

Go 的错误处理始终是体现最突出的一块中央,许许多多的同学都提出了各种提案,例如:引入 try-catch、用 panic 代替 if err != nil、引入新的关键字等。但这些都被一一驳回了。

不过社区仍然还没放弃,周末看到有一个新的提案《proposal: runtime: add parameters to recover to only return specific types》挺有意思。

明天就由煎鱼带大家一起学习。

语法阐明

Go 的 panic、recover、defer 的根本应用形式。如下代码:

package mainimport "fmt"func mayPanic() {    panic("a problem")}func main() {    defer func() {        if r := recover(); r != nil {            fmt.Println("Recovered. Error:\n", r)        }    }()    mayPanic()    fmt.Println("After mayPanic()")}

输入后果:

Recovered. Error: a problem

新提案

因为有 Go1 兼容性保障,新提案是在原有的 recover 函数上动小手术。心愿能够现在运行时的 recover 中退出参数,仅反对返回特定的类型

函数签名:

recover(except ...interface{})

案例代码:

defer func(){    if err := recover(&MyError{}, &HelloError{}); err != nil {        switch e := err.(type) {        case *MyError:            fmt.Println(e)        case *HelloError:            fmt.Println(e)        }    }}

下面代码中,recover 函数只反对传入 MyError 和 HelloError 的指针类型。再在解决逻辑中依据所传入的谬误类型,进行断言分类,实际上去做不同的逻辑解决。

重点就是限定 recover 入参类型。

探讨

有些小伙伴可能发现了,比照看看 PHP 的 try-catch 的用法,与后面的提案代码是不是有好几分神似呢?

如下代码:

try {    ...}catch (Exception $e) {    echo $e->getMessage();}catch (InvalidArgumentException $e) {    echo $e->getMessage();}catch (BarException $ex){    echo $e->getMessage();}catch (FooException $ex){    echo $e->getMessage();}

实质上这个新的提案是想在不毁坏 Go1 兼容性的状况下,在 Go 中实现 try-catch 的形式。

社区在交换时,也发现了用户在现有机制下能够自主实现 Go 的类 try-catch 的模式。

如下代码:

func Recover(expect ...interface{}) interface{} {    if err := recover(); err != nil {        if len(expect) == 0 {            return err        }        rv1 := reflect.Indirect(reflect.ValueOf(err))        for _, e := range expect {            rv2 :=  reflect.Indirect(reflect.ValueOf(e))            if rv1.Type() == rv2.Type() {                return err            }        }        panic(err)    }    return nil}

这个自制办法的问题是每次 Recover panic 都会将堆栈深度减少 2。因而还是寄希望于 Go 官网可能在运行时反对。

在 Go 规范库的用处比照上,也有产生肯定的作用,其波及到的代码根本为:

规范库中至多有以下中央能够复用:

  • text/template/exec.go
  • go/parser/interface.go
  • go/types/check.go
  • go/ast/print.go
  • encoding/json/encode.go
  • encoding/gob/error.go

总结

这个提案实质上是心愿通过在 recover 函数中减少入参管制,再配合外部逻辑实现相似 Go 版本的 try-catch 的错误处理机制模型,且理论在 Go 规范库中有复用的空间。

但现阶段该提案也是同意和拥护参半,也有人认为能够用户本人实现,那就没必要加大复杂度,去做这个收益不够大的实现。

你感觉这能补全 Go 错误处理的一些机制缺点吗?

文章继续更新,能够微信搜【脑子进煎鱼了】浏览,本文 GitHub github.com/eddycjy/blog 已收录,学习 Go 语言能够看 Go 学习地图和路线,欢送 Star 催更。

Go 图书系列

  • Go 语言入门系列:初探 Go 我的项目实战
  • Go 语言编程之旅:深刻用 Go 做我的项目
  • Go 语言设计哲学:理解 Go 的为什么和设计思考
  • Go 语言进阶之旅:进一步深刻 Go 源码