golang gorm 使用in_GCTT 出品 | 在 Go 中使用命名返回变量捕获 panic

23219f19cc07b194931e51cda3ffeeca.png

这将是一个简短的帖子,灵感来源于 Sean Kelly 十一月份的推特。

我发现了一个在 golang 中使用指定的返回值的原因并且现在我感到潸然泪下。

— Sean Kelly (@StabbyCutyou) 2017年11月15日

其目标是为了记录并说明一种有必要使用到命名返回变量的情况,所以说让我们进入正题。

想象你正在编写一些用了可能 panic 的函数的代码,并且无论什么原因(第三方库,向后兼容,等等)你都不能改变那些函数。

func pressButton() {  fmt.Println("I'm Mr. Meeseeks, look at me!!") // other stuff then happens, but if Jerry asks to  // remove 2 strokes from his golf game... panic("It's gettin' weird!")}

你仍然需要用到那个函数,不过如果它发生异常,而你想要捕获到这个 panic 并将它作为一个 error 返回,那么你应该写一些类似这样的代码:

func doStuff() error {  var err error // If there is a panic we need to recover in a deferred func defer func() { if r := recover(); r != nil { err = errors.New("the meeseeks went crazy!") } }() pressButton() return err}

在 Go Playground 上执行它 - https://play.golang.org/p/wzkjKGqFPL

之后你 go run 了你的代码然而...这是什么?你的 error 是 nil 值,甚至是在代码发生异常的时候。这并不是我们想要的!

为什么会发生这种情况?

虽然最初看起来我们的代码返回的是我们在函数开始时创建的 var err error,但事实上,我们的程序永远不会到达这一行代码。这意味着它永远不会返回特定的 err 变量,而且在我们的 defer 函数内部改变它,最终会变得毫无意义。

在调用 pressButton 之后添加一个 Println,但在返回之前,确实有助于说明这一点:

pressButton() // Nothing below here gets executed!fmt.Println("we got here!") return err

在 Go Playground 上执行它 - https://play.golang.org/p/Vk0DYs20eB

我们该如何修复它

为了修复这个问题,我们可以简单地使用命名返回变量。

func doStuff() (err error) {  // If there is a panic we need to recover in a deferred func defer func() { if r := recover(); r != nil { err = errors.New("the meeseeks went crazy!") } }() pressButton() return err}

在 Go Playground 上执行它 - https://play.golang.org/p/bqGOroPjQJ

最终的代码看起来非常的相似,不过通过命名我们的返回变量,当我们声明这个函数时,我们的程序将会立刻返回这个 err 变量,即使我们从未触碰到 doStuff 函数的末尾的返回语句。由于这个细微的差别,现在我们可以更改被我们 defer 的函数中的 err 变量,并且成功地捕获到这个 panic。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值