内容简介:作者:Stefan Nilsson原文网址:Panics 类似于 C++ 和 Java 异常,但仅适用于运行时错误,例如跟随一个 nil 指针或试图对数组访问超出范围的索引。为了表示诸如文件结束之类的事件,Go 程序使用内置
作者:Stefan Nilsson
原文网址: yourbasic.org/golang/reco…
Panic 是 Go 中的一个异常
Panics 类似于 C++ 和 Java 异常,但仅适用于运行时错误,例如跟随一个 nil 指针或试图对数组访问超出范围的索引。为了表示诸如文件结束之类的事件,Go 程序使用内置 error
类型。有关错误的更多信息,请参见 错误处理最佳实践 和 3种创建错误的简单方法 。
Panic 停止 goroutine 的正常执行
- 程序出现 panic 时,它将立即开始展开调用堆栈。
- 一直持续到程序崩溃并打印堆栈跟踪,
- 或直到调用内置的恢复功能。
panic 是由运行时错误或对内置函数 panic
的显式调用引起的。
堆栈跟踪记录
堆栈跟踪记录 —— 所有活动堆栈帧的报告 —— 通常在 panic 发生时将其打印到控制台。堆栈跟踪对于调试非常有用:
- 您不仅可以看到错误发生的地方,
- 而且可以看到程序是如何到达这个地方的。
解释堆栈跟踪
这是一个堆栈跟踪的示例:
goroutine 11 [running]: testing.tRunner.func1(0xc420092690) /usr/local/go/src/testing/testing.go:711 +0x2d2 panic(0x53f820, 0x594da0) /usr/local/go/src/runtime/panic.go:491 +0x283 github.com/yourbasic/bit.(*Set).Max(0xc42000a940, 0x0) ../src/github.com/bit/set_math_bits.go:137 +0x89 github.com/yourbasic/bit.TestMax(0xc420092690) ../src/github.com/bit/set_test.go:165 +0x337 testing.tRunner(0xc420092690, 0x57f5e8) /usr/local/go/src/testing/testing.go:746 +0xd0 created by testing.(*T).Run /usr/local/go/src/testing/testing.go:789 +0x2de 复制代码
可以从下至上阅读:
-
testing.(*T).Run
调用了testing.tRunner
, -
testing.tRunner
调用了bit.TestMax
, -
bit.TestMax
调用了bit.(*Set).Max
, -
bit.(*Set).Max
调用了panic
, -
panic
调用了testing.tRunner.func1
缩进的行显示了调用该函数的源文件和行号。十六进制数字表示参数值,包括指针和内部数据结构的值。 Go 中的堆栈跟踪 具有更多详细信息。
打印并记录堆栈跟踪
要打印当前 goroutine 的堆栈跟踪,请使用包 runtime/debug 中的 debug.PrintStack 。
您还可以通过调用 runtime.Stack 以编程方式检查当前的堆栈跟踪
详细程度
变量 GOTRACEBACK 控制 Go 程序失败时生成的输出量。
GOTRACEBACK = none GOTRACEBACK = single GOTRACEBACK = all GOTRACEBACK = system
恢复和捕获 Panic
内置的 recover 函数可用于重新获得对异常程序的控制并恢复正常执行。
- 调用 recover 将停止展开并返回传递给 panic 的参数。
- 如果 goroutine 没有异常,则恢复将返回 nil。
因为展开时运行的唯一代码是在 defer 函数内部,所以 recover 仅在此类函数内部有用。
Panic 处理程序示例
func main() { n := foo() fmt.Println("main received", n) } func foo() int { defer func() { if err := recover(); err != nil { fmt.Println(err) } }() m := 1 panic("foo: fail") m = 2 return m } 复制代码
foo: fail main received 0 复制代码
由于 panic 是在 foo 返回值之前发生的,因此 n 仍然具有其初始零值。
返回值
要在发生 panic 时返回值,必须使用命名返回值。
func main() { n := foo() fmt.Println("main received", n) } func foo() (m int) { defer func() { if err := recover(); err != nil { fmt.Println(err) m = 2 } }() m = 1 panic("foo: fail") m = 3 return m } 复制代码
foo: fail main received 2 复制代码
测试 Panic(实用功能)
在此示例中,我们使用反射来检查接口变量列表是否具有与给定函数的参数相对应的类型。如果是这样,我们使用这些参数调用该函数以检查是否有 panic。
// Panics tells if function f panics with parameters p. func Panics(f interface{}, p ...interface{}) bool { fv := reflect.ValueOf(f) ft := reflect.TypeOf(f) if ft.NumIn() != len(p) { panic("wrong argument count") } pv := make([]reflect.Value, len(p)) for i, v := range p { if reflect.TypeOf(v) != ft.In(i) { panic("wrong argument type") } pv[i] = reflect.ValueOf(v) } return call(fv, pv) } func call(fv reflect.Value, pv []reflect.Value) (b bool) { defer func() { if err := recover(); err != nil { b = true } }() fv.Call(pv) return } 复制代码
扫描下方二维码,关注 Feed
, 定期推送最新随笔
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:- 译文 | 推荐信:程序排错
- Protobuf -java基础教程(译文)
- 译文: Basics of Futexes
- 跨站请求伪造已经死了!(译文)
- (译文)通过一个例子理解paxos算法
- iOS·UIView Apple 官方文档译文
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Powerful
Patty McCord / Missionday / 2018-1-25
Named by The Washington Post as one of the 11 Leadership Books to Read in 2018 When it comes to recruiting, motivating, and creating great teams, Patty McCord says most companies have it all wrong. Mc......一起来看看 《Powerful》 这本书的介绍吧!