在golang中处理逻辑错误与编程错误的惯用方法

时间:2018-06-08 14:25:07

标签: go error-handling idiomatic

我一直在使用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();
}

使用此签名,我可以知道我错误地使用具有id的Job调用run(obj);,实际上我可以区分我的脚本是否有错误或者我是以错误的方式使用api

NotCompletedJob是一个已检查的异常,所以我必须处理它,但IllegalArgumentException不是这样,我可以随时获取它。捕获IllegalArgumentException或任何其他RuntimeException并不总是被认为是一种好习惯,因为它们表明您从程序员的角度出现错误,并且它不是可能的预期错误,如NotCompletedJob。< / p>

话虽如此,我如何区分编程错误(例如,错误的用法)与预期的错误(脚本没有完成确定)与当前的CombinedOutput()实现?

为了澄清我的担忧,我并不是说当前的CombinedOuput实现是错误的,但我不明白调用者如何区分是否是正在执行的命令的错误或由于他的错误导致的错误api用法。

我认为,当调用者以错误的方式使用api时,最好的方法是恐慌,就像调用者将nil引用传递给期望非零引用的函数的情况一样(实际上这是是目前的行为。)

1 个答案:

答案 0 :(得分:3)

  

我来自Java World,当你使用某种方法时出错了   然后你收到一个RuntimeException。

你现在正处于围棋世界。因此,该论点无效。放弃Java。

  

The Go Programming Language Specification

     

Handling panics

     

两个内置功能,恐慌和恢复,协助报告和   处理运行时恐慌和程序定义的错误条件。

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

执行函数F时,显式调用panic或运行时   panic终止F的执行。任何由F推迟的函数都是   然后像往常一样执行。接下来,F的调用者运行任何延迟函数   运行,依此类推,直至由顶级函数推迟   执行goroutine。那时,程序终止了   报告错误条件,包括参数的值   恐慌。此终止序列称为恐慌。

  

Go Blog

     

Defer, Panic, and Recover

     

Go库中的约定即使在包使用时也是如此   内部恐慌,其外部API仍然存在明显的错误   返回值。

  

Go Code Review Comments

     

此页面收集在Go代码审核期间发表的常见评论,所以   短头可以提到一个详细的解释。   这是常见错误的清单,而非风格指南。

     

Don't Panic

     

https://golang.org/doc/effective_go.html#errors。不要惊慌失措   用于正常的错误处理。使用错误和多个返回值。

  

Effective Go

     

Errors

     

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

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

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