Go 的 Panics 处理
译者:baiyutang
原文:https://www.digitalocean.com/community/tutorials/handling-panics-in-go
介绍
程序遇到的错误可以分为两大类:程序员预料到的错误和程序员没有预料到的错误。我们在前两篇关于错误处理的文章中介绍的 error
接口,主要处理我们在编写 Go 程序时所预期的错误。error
接口甚至允许我们检测到函数调用中发生罕见错误的可能性,因此我们可以在这些情况下作出适当的响应。
Panics 属于第二类错误,这是程序员始料未及的。这些不可预见的错误会导致程序自动终止并退出正在运行的 Go 程序。常见的错误往往是造成 Panics 的原因。在本教程中,我们将研究几种常见操作在 Go 中产生 Panics 的方法,以及避免这些 Panics 的方法。我们还将使用 defer
语句和 recover
函数来捕捉恐慌,以免它们有机会意外地终止正在运行的 Go 程序。
理解 Panic
在 Go 中有一些操作会自动返回 Panics 并停止程序。常见的操作包括索引超出容量的数组、执行类型断言、在空指针上调用方法、错误地使用互斥体以及尝试使用关闭的通道。这些情况大多数是由于编程时所犯的错误造成的,编译器在编译程序时无法检测到这些错误。
由于 Panics 包含了对解决问题有用的细节,开发人员通常使用 Panics 作为他们在程序开发过程中犯错误的提示。
越界 Panic
当您试图访问超出片长度或数组容量的索引时,Go 运行时将产生 Panics。
下面的例子犯了一个常见的错误,即尝试使用 len
内置函数返回的切片的长度来访问切片的最后一个元素。试着运行下面的代码,看看为什么会产生 Panics:
这会有如下输出:
Panic 解剖
Panics 由提示 Panics 原因的消息和堆栈跟踪组成,堆栈跟踪帮助您定位在代码中的何处产生了 Panics。
任何 Panics 的第一部分都是信息。它总是以字符串 panic:
开始,后面跟着一个根据引起 Panics 的原因而变化的字符串。上次演示的 Panics 传达了这样一个信息:
Nil 接受者
Go 编程语言的指针指向运行时存在于计算机内存中的某种类型的特定实例。指针可以假设值为 nil
,表示它们没有指向任何东西。当我们试图在一个 nil
指针上调用方法时,Go 运行时将产生 Panics。类似地,作为接口类型的变量在对其调用方法时也会产生 Panics 。要查看在这些情况下产生的 Panics,请尝试以下示例:
Panics 将会是这样:
使用 panic 内建函数
我们也可以使用内置的 panic
函数来产生我们自己的 Panics。它接受一个字符串作为参数,这是 Panics 将产生的消息。通常,此消息比重写代码以返回错误要简单。此外,我们可以在我们自己的包中使用它来向开发人员表明,他们在使用我们包的代码时可能犯了错误。只要有可能,最佳实践是尽量将错误值返回给我们的包的消费者。
Panics 将会是这样:
defer 函数
您的程序可能有必须正确清理的资源,即使在运行时正在处理 panic 时也是如此。Go 允许延迟执行函数调用,直到调用函数的函数完成执行。延迟函数甚至在出现恐慌时也会运行,并被用作一种安全机制,以防止 Panics 造成的混乱。函数被延迟是通过像往常一样调用它们,然后在整个语句前面加上 关键字,如defer sayHello()
。运行此示例,查看在产生恐慌时如何打印消息:
此例的 Panics 将会是这样
Panic 处理
用 recover 检测 Panic
recover
函数依靠错误值来确定是否发生了恐慌。因为 panic
函数的参数是一个空接口,所以它可以是任何类型。任何接口类型(包括空接口)的零值都是 nil
。必须注意避免以 nil
作为参数引起 panic
,如下例所示:
总结
我们已经看到了在 Go 中许多产生 Panics 的方法,以及如何使用内置的 recover
恢复 Panics。虽然您自己可能并不一定使用 panic
,但是从 Panics 中适当恢复是使 Go 应用程序具备生产能力的重要步骤。
版权声明: 本文为 InfoQ 作者【baiyutang】的原创文章。
原文链接:【http://xie.infoq.cn/article/88d59df1fa095c42e030fd546】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论