对于下面的代码,如果没有给出文件参数,那么第9行panic: runtime error: index out of range
将如预期的那样抛出异常。
当直接向它传递导致死机的东西(os.Args[1]
)时,我如何“捕获”这个死机并处理它?就像PHP中的try/catch或Python中的try/except。
我在StackOverflow上进行了搜索,但我没有找到任何答案。
package main
import (
"fmt"
"os"
)
func main() {
file, err := os.Open(os.Args[1])
if err != nil {
fmt.Println("Could not open file")
}
fmt.Printf("%s", file)
}
8条答案
按热度按时间n7taea2i1#
恐慌程序可以通过内置的
recover()
函数恢复:recover
函数允许程序管理恐慌goroutine的行为。假设一个函数G
推迟了一个调用recover
的函数D
,并且在执行G
的同一个goroutine上的一个函数中发生了panic。当延迟函数的运行达到D
时,D
对recover
的调用的返回值将是传递给panic
的调用的值。如果D
正常返回,而没有启动新的panic
,则恐慌序列停止。在这种情况下,G
和panic
之间调用的函数的状态将被丢弃,并恢复正常执行。G
在D
之前延迟的任何函数都将运行,G
的执行将返回到其调用方而终止。当goroutine没有panicking或者
recover
没有被延迟函数直接调用时,recover
的返回值是nil
。相反,如果一个goroutine出现了panicing,并且recover
被一个deferred函数直接调用,那么recover
的返回值肯定不会是nil
。为了确保这一点,使用nil
接口值(或非类型化的nil
)调用panic
会导致运行时死机。下面是一个如何使用它的示例:
请注意,恐慌往往不是正确的解决方案。Go范式是显式地检查错误。一个程序只有在正常程序执行期间不发生死机的情况下才应该死机。例如,无法打开文件是可能发生的事情,不应该导致恐慌,而内存不足值得恐慌。然而,这种机制的存在甚至能够捕获这些情况,并可能优雅地关闭。
yqhsw0fo2#
Go不是Python,在使用它之前,你应该正确地检查args:
wn9m85ua3#
一些Golang官方软件包使用 panic/defer+recover 作为 throw/catch,但仅当它们需要展开大型调用堆栈时。在 *Golang的json包中 * 使用 panic/defer+recover 作为 throw/catch 是最优雅的解决方案。
从http://blog.golang.org/defer-panic-and-recover
有关panic和recover的真实示例,请参阅Go标准库中的 *json包 。它使用一组递归函数对JSON编码的数据进行解码。当遇到格式错误的JSON时, 解析器调用panic将堆栈展开到顶级函数调用,该函数从panic中恢复 * 并返回适当的错误值(请参阅decode.go中decodeState类型的'error'和'unmarshal'方法)。
在http://golang.org/src/encoding/json/decode.go上搜索
d.error(
在您的示例中,“惯用”的解决方案是在使用参数之前检查参数,正如其他解决方案所指出的那样。
但是,如果你想/需要抓住任何你可以做的事情:
62o28rlo4#
第一:你不会想这么做的。Try-catch样式的错误处理不是错误处理。在Go语言中,你会先检查
len(os.Args)
,然后只访问元素1(如果存在)。对于罕见的情况,你需要捕捉恐慌(你的情况是不是其中之一!)结合使用
defer
和recover
。请访问http://golang.org/doc/effective_go.html#recoverbweufnob5#
我们可以使用recover来管理恐慌,而无需停止进程。通过在任何使用defer的函数中调用recover,它都会将执行返回给调用函数。Recover返回两个值,一个是布尔值,另一个是要恢复的接口。使用类型Assert,我们可以得到底层错误值。您还可以使用recover打印底层错误。
mkh04yzy6#
我不得不在一个测试案例中捕捉恐慌。我被重定向到这里。
func.go
func_test.go
使用自https://github.com/golang/go/commit/e4f1d9cf2e948eb0f0bb91d7c253ab61dfff3a59(参考自VonC)
eufgjt7s7#
请注意,在issue 14965之后,go 1.7可能会更改对panic Execution 错误(例如尝试索引数组越界触发器)的恢复处理
参见CL 21214及其试验:
运行时:make execution error panic values实现
Error
接口使执行panics实现运行时panics(specs)所要求的Error,而不是带有字符串的panics。
当您恢复一个panic错误时,您可以执行以下操作:
这仍在评估中,并作为Dave Cheney。提到:
我不知道人们目前在做什么,但从我的经验来看,这已经被打破了很长一段时间,没有人抱怨,所以他们要么明确地依赖于破碎的行为,或者没有人在乎。无论哪种方式,我认为这是一个好主意,以避免作出这种改变。
sf6xfgos8#
虽然Go语言中的
panic
不是惯用的,不应该在其他编程语言中用作异常,但有时确实需要“捕获”它们。在这些情况下,我发现定义一个
CatchPanic
实用程序将panic
转换为可检查的error
以最大限度地减少与Go语言习惯用法的差异是很有用的。举例来说:
用法示例(过于简化..):
lambda参数的返回值可以根据其他用例进行调整。
请注意,在可能的情况下,建议不要在Go中依赖恐慌捕获,并且在访问之前进行检查是更可取的。