hedgehogues Asked:2022-02-26 17:37:19 +0000 UTC2022-02-26 17:37:19 +0000 UTC 2022-02-26 17:37:19 +0000 UTC 推迟、恢复和恐慌,而不是 try-catch 772 它与大多数 defer-recover-panic 构造语言中的 try-catch 有何不同? 恐慌如何影响性能?我正在考虑在某些地方使用延迟+恢复+恐慌,而不是不断地将错误转发到顶部。 除了性能 7 之外还有哪些细微差别? golang 1 个回答 Voted Best Answer RTK 2022-02-28T22:38:52Z2022-02-28T22:38:52Z panic/recover与其他语言不同的try/catch是,它完全中断了当前函数的执行。 为了更清楚: function doSomething() { throw "panic"; } (() => { try { doSomething(); } catch(e) { console.log(e); } console.log("after try/catch") })() package main import ( "fmt" "runtime/debug" ) func doSomething() { panic("panic") } func main() { defer func() { if err := recover(); err != nil { fmt.Printf("%s: %s", err, debug.Stack()) } }() doSomething() fmt.Print("after panic") } 在第一个例子中,文本after try/catch将被显示,在第二个例子中after panic它不会被显示,因为 该函数main将完成执行。 也recover可以只有一个,粗略地说,好像函数的整个主体都被包裹在了 中try/catch,这使得它的灵活性降低了。我读到这是故意这样做以避免滥用。 至于性能,这个问题相当复杂,肯定panic/recover更慢,但我发现很难说出区别,因为用相同的应用程序编写基准测试相当困难。 在任何情况下我都不声称基准的正确性,我希望在评论中得到同事的更正。 i5在笔记本电脑上运行go version go1.15 linux/amd64 BenchmarkPanicDefer-4 3006555 353 ns/op BenchmarkErrorCatch-4 1000000000 0.502 ns/op 我尝试编写基准测试: package main import ( "errors" "testing" ) func getPanic() { panic("") } func PanicDefer() { defer func() { if err := recover(); err != nil { // do something } }() getPanic() } func getError() error { return errors.New("") } func CatchError() { if err := getError(); err != nil { // do something } } func BenchmarkPanicDefer(b *testing.B) { for i := 0; i < b.N; i++ { PanicDefer() } } func BenchmarkErrorCatch(b *testing.B) { for i := 0; i < b.N; i++ { CatchError() } } 很明显,条件并不完全相等,我试图让它们尽可能接近实际应用。 通常,“错误”和“异常”之间的界限相当模糊,高度依赖于上下文。在其他语言中,try/catch这是两种情况的通用解决方案。在我看来,如果panic/recover在特定的地方使用它会使代码更干净,那么没有什么能阻止你以这种方式编写它。
panic/recover与其他语言不同的try/catch是,它完全中断了当前函数的执行。为了更清楚:
在第一个例子中,文本
after try/catch将被显示,在第二个例子中after panic它不会被显示,因为 该函数main将完成执行。也
recover可以只有一个,粗略地说,好像函数的整个主体都被包裹在了 中try/catch,这使得它的灵活性降低了。我读到这是故意这样做以避免滥用。至于性能,这个问题相当复杂,肯定
panic/recover更慢,但我发现很难说出区别,因为用相同的应用程序编写基准测试相当困难。在任何情况下我都不声称基准的正确性,我希望在评论中得到同事的更正。
i5在笔记本电脑上运行go version go1.15 linux/amd64我尝试编写基准测试:
很明显,条件并不完全相等,我试图让它们尽可能接近实际应用。
通常,“错误”和“异常”之间的界限相当模糊,高度依赖于上下文。在其他语言中,
try/catch这是两种情况的通用解决方案。在我看来,如果panic/recover在特定的地方使用它会使代码更干净,那么没有什么能阻止你以这种方式编写它。