大家好,我是煎鱼。
目前创新互联公司已为1000多家的企业提供了网站建设、域名、虚拟空间、网站运营、企业网站设计、柳州网站维护等服务,公司将坚持客户导向、应用为本的策略,正道将秉承"和谐、参与、激情"的文化,与客户和合作伙伴齐心协力一起成长,共同发展。
Go 的错误处理一直是表现最突出的一块地方,许许多多的同学都提出了各种提案,例如:引入 try-catch、用 panic 代替 if err != nil、引入新的关键字等。但这些都被一一驳回了。
不过社区依然还没放弃,周末看到有一个新的提案《proposal: runtime: add parameters to recover to only return specific types[1]》挺有意思。
今天就由煎鱼带大家一起学习。
Go 的 panic、recover、defer 的基本使用方式。如下代码:
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 中加入参数,仅支持返回特定的类型。
函数签名:
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 标准库的用途对比上,也有产生一定的作用,其涉及到的代码基本为:
标准库中至少有以下地方可以复用:
这个提案本质上是希望通过在 recover 函数中增加入参控制,再配合内部逻辑实现类似 Go 版本的 try-catch 的错误处理机制模型,且实际在 Go 标准库中有复用的空间。
但现阶段该提案也是赞同和反对参半,也有人认为可以用户自己实现,那就没必要加大复杂度,去做这个收益不够大的实现。
你觉得这能补全 Go 错误处理的一些机制缺陷吗?
[1]proposal: runtime: add parameters to recover to only return specific types: https://github.com/golang/go/issues/50424
[2]text/template/exec.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/text/template/exec.go;l=156
[3]go/parser/interface.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/go/parser/interface.go;l=97
[4]go/types/check.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/go/types/check.go;l=235
[5]go/ast/print.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/go/ast/print.go;l=53
[6]encoding/json/encode.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/encoding/json/encode.go;l=317
[7]encoding/gob/error.go: https://cs.opensource.google/go/go/+/refs/tags/go1.17.5:src/encoding/gob/error.go;l=32
分享文章:试试动Gorecover刀子,看看能不能优化错误处理?
网站链接:http://www.gawzjz.com/qtweb/news11/205111.html
网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联