首页 > 解决方案 > 在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.Stderrc.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 引用的函数时一样(实际上这是当前的行为)。

标签: goerror-handlingidioms

解决方案


我来自 Java World,当您以错误的方式使用某些方法时,您会收到 RuntimeException。


你现在在围棋世界。因此,该论点是无效的。放弃 Java。


Go 编程语言规范

处理恐慌

两个内置函数,恐慌和恢复,有助于报告和处理运行时恐慌和程序定义的错误情况。

func panic(interface{}) 
func recover() interface{}

在执行函数 F 时,显式调用 panic 或运行时 panic 会终止 F 的执行。任何被 F 延迟的函数都会照常执行。接下来,运行由 F 的调用者运行的任何延迟函数,依此类推,直到执行 goroutine 中的顶级函数延迟。此时,程序终止并报告错误情况,包括 panic 的参数值。这种终止序列称为恐慌。


围棋博客

推迟、恐慌和恢复

Go 库中的约定是,即使包在内部使用了 panic,它的外部 API 仍然会显示显式的错误返回值。


Go 代码审查评论

本页收集了 Go 代码评审过程中的常见评论,以便一个详细的解释可以简写参考。这是一份常见错误的清单,而不是风格指南。

不要恐慌

请参阅https://golang.org/doc/effective_go.html#errors。不要将恐慌用于正常的错误处理。使用错误和多个返回值。


有效围棋

错误

向调用者报告错误的常用方法是将错误作为额外的返回值返回。


您的 Go 服务器程序同时处理 100,000 个客户端。如果发生错误,报告并处理;始终检查错误。不要使用panic. Go 包不应该panic

阅读 Go 文档和 Go 标准库代码。


推荐阅读