标准库对 API 的误用感到 panic。例如,reflect
在许多情况下,如果一个值的访问方式表明它被误读,就会发出 panic。这类似于对核心语言错误的 panic,如访问一个越界的 slice 元素。代码审查和测试应该发现这样的错误,这些错误预计不会出现在生产代码中。这些 panic 作为不依赖库的不变性检查,因为标准库不能访问谷歌代码库使用的levelled log
包。
另一种情况下,panic 可能是有用的,尽管不常见,是作为一个包的内部实现细节,在调用链中总是有一个匹配的恢复。解析器和类似的深度嵌套、紧密耦合的内部函数组可以从这种设计中受益,其中管道错误返回增加了复杂性而没有价值。这种设计的关键属性是,这些 panic 永远不允许跨越包的边界,不构成包的API的一部分。这通常是通过一个顶层的延迟恢复来实现的,它将传播的 panic 转化为公共API表面的返回错误。
当编译器无法识别不可到达的代码时,例如使用像log.Fatal
这样不会返回的函数时,也会使用 Panic:
// Good:func answer(i int) string { switch i { case 42: return "yup" case 54: return "base 13, huh" default: log.Fatalf("Sorry, %d is not the answer.", i) panic("unreachable") }}
不要在标志被解析之前调用log
函数。如果你必须在 init
函数中死亡,可以接受用 panic 来代替日志调用。