go - 在golang中处理逻辑错误与编程错误的惯用方法
问题描述
我一直在使用 golang 来自动化一些部署过程,我不得不使用exec
包来调用一些 bash 脚本。
我使用exec.Command("/home/rodrigo/my-deploy.sh").CombinedOutput()
并看到了他的实现
func (c *Cmd) CombinedOutput() ([]byte, error) {
if c.Stdout != nil {
return nil, errors.New("exec: Stdout already set")
}
if c.Stderr != nil {
return nil, errors.New("exec: Stderr already set")
}
var b bytes.Buffer
c.Stdout = &b
c.Stderr = &b
err := c.Run()
return b.Bytes(), err
}
c.Stdout
我意识到你在使用时不能分配CombinedOutput()
,我认为这没关系,但它被告知 api 调用者的方式是不正确的。
CombinedOutput()
当你以不好的方式使用它时返回一个错误,所以如果你要使用它,CombinedOutput()
那么你不应该分配c.Stderr
或c.Stdout
以前,如果你这样做,那么你将收到一个错误。
但是这个错误不是因为你的脚本抛出错误,而是因为你使用了错误的 api,在这种情况下,我相信你应该得到一个panic
,因为不应该处理错误的 api 使用(我认为)。
我来自 Java World,例如,当您以错误的方式使用某些方法时,您会收到一个RuntimeException
.
public void run(Job job) throws NotCompletedJob {
if (job.getId() != null) {
throw new IllegalArgumentException("This job should not have id");
}
job.setId(calculateId());
job.run();
}
有了这个签名,我可以知道我run(obj);
用一个有 id 的 Job 调用是错误的,事实上我可以区分我的脚本是否有错误,或者我以错误的方式使用 api。
NotCompletedJob
是一个已检查的异常,所以我必须处理它,但IllegalArgumentException
不是,所以我可以随时得到它。捕捉IllegalArgumentException
或任何其他RuntimeException
方法并不总是被认为是一种好的做法,因为从程序员的角度来看,它们表明您有一个错误,这不是一个可能的预期错误,例如NotCompletedJob
.
话虽如此,我如何区分当前实现的编程错误(例如错误的 api 用法)和预期错误(脚本未正常完成)CombinedOutput()
?
为了澄清我的担忧,我并不是说当前的 CombinedOuput 实现是错误的,但我不明白调用者如何区分它是执行命令的错误还是由他的错误 api 使用引起的错误。
我相信最好的方法是在调用者以错误的方式使用 api 时惊慌失措,就像调用者将 nil 引用传递给期望非 nil 引用的函数时一样(实际上这是当前的行为)。
解决方案
我来自 Java World,当您以错误的方式使用某些方法时,您会收到 RuntimeException。
你现在在围棋世界。因此,该论点是无效的。放弃 Java。
两个内置函数,恐慌和恢复,有助于报告和处理运行时恐慌和程序定义的错误情况。
func panic(interface{}) func recover() interface{}
在执行函数 F 时,显式调用 panic 或运行时 panic 会终止 F 的执行。任何被 F 延迟的函数都会照常执行。接下来,运行由 F 的调用者运行的任何延迟函数,依此类推,直到执行 goroutine 中的顶级函数延迟。此时,程序终止并报告错误情况,包括 panic 的参数值。这种终止序列称为恐慌。
围棋博客
Go 库中的约定是,即使包在内部使用了 panic,它的外部 API 仍然会显示显式的错误返回值。
本页收集了 Go 代码评审过程中的常见评论,以便一个详细的解释可以简写参考。这是一份常见错误的清单,而不是风格指南。
请参阅https://golang.org/doc/effective_go.html#errors。不要将恐慌用于正常的错误处理。使用错误和多个返回值。
向调用者报告错误的常用方法是将错误作为额外的返回值返回。
您的 Go 服务器程序同时处理 100,000 个客户端。如果发生错误,报告并处理;始终检查错误。不要使用panic
. Go 包不应该panic
。
阅读 Go 文档和 Go 标准库代码。
推荐阅读
- html - 有没有办法在不增加图像大小的情况下增加透明空间?
- python - 为变量赋值并在下一行代码中使用它还是直接访问一个值?哪个更快?在蟒蛇
- tailwind-css - 如何使用tailwindcss 2.1制作水平滚动表格?
- javascript - 代码只运行第一个 if 函数,或者有时同时运行所有函数
- perl - Perl:使重复哈希键的声明成为致命错误?
- git - 使用 git 在 CI 中创建测试分支
- react-native - 如何在离线反应原生中播放加密视频?
- r - 错误:在 R 中的 sparklyr 中收集字数时出现“在字符串中嵌入 nul”
- semantic-ui - 语义 UI - 如何将下拉菜单清除为默认值?
- ios - SKLabel 在分配给特定元素时未显示