大家好,我是煎鱼。
Go 的错误处理始终是体现最突出的一块中央,许许多多的同学都提出了各种提案,例如:引入 try-catch、用 panic 代替 if err != nil、引入新的关键字等。但这些都被一一驳回了。
不过社区仍然还没放弃,周末看到有一个新的提案《proposal: runtime: add parameters to recover to only return specific types》挺有意思。
明天就由煎鱼带大家一起学习。
语法阐明
Go 的 panic、recover、defer 的根本应用形式。如下代码:
<code class="go">package main import "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 中退出参数,仅反对返回特定的类型。
函数签名:
<code class="go">recover(except ...interface{})
案例代码:
<code class="go">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 的用法,与后面的提案代码是不是有好几分神似呢?
如下代码:
<code class="php">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 的模式。
如下代码:
<code class="go">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 源码