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

golang中处理逻辑错误与编程错误的惯用方法,go,error-handling,idioms,Go,Error Handling,Idioms,我一直在使用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") }

我一直在使用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
}
我意识到在使用CombinedOutput时不能分配c.Stdout,我认为这没关系,但是通知api调用方的方式是不正确的

CombinedOutput以错误的方式使用时返回错误,因此,如果要使用CombinedOutput,则不应在前面分配c.Stderr或c.Stdout,如果这样做,则将收到错误

但是这个错误并不是因为你的脚本抛出了一个错误,而是因为你使用的api是错误的,在这种情况下,我认为你应该感到恐慌,因为我认为不应该处理糟糕的api使用

我来自Java世界,例如,当您以错误的方式使用某些方法时,您会收到一个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();
}
有了这个签名,我就知道我打错了runobj;对于一个有id的作业,事实上,我可以区分我的脚本是否有错误,或者我以错误的方式使用api

NotCompletedJob是一个选中的异常,所以我必须处理它,但IllegalArgumentException不是,所以我可以随时获取它。捕获IllegalArgumentException或任何其他RuntimeException并不总是被认为是一种好的做法,因为从程序员的角度来看,它们表明您有一个错误,并且不像NotCompletedJob那样是一个可能的预期错误

话虽如此,我如何区分编程错误(例如坏api用法)和预期错误(脚本未在当前组合输出实现中正常完成)

为了澄清我的担忧,我并不是说CombinedOuput的当前实现是错误的,但我不理解调用方如何区分这是正在执行的命令的错误,还是由于错误的api使用而导致的错误

我认为最好的方法是在调用方以错误的方式使用api时惊慌失措,就像调用方将nil引用传递给期望非nil引用的函数时一样——事实上,这是当前的行为

我来自Java世界,当你使用错误的方法时 这样您就会收到一个RuntimeException

你现在在忙碌的世界里。因此,这个论点是无效的。放弃Java

两个内置功能“紧急”和“恢复”,有助于报告和恢复 处理运行时死机和程序定义的错误条件

func panic(interface{}) 
func recover() interface{}
在执行函数F时,显式调用panic或运行时 panic终止F的执行。F延迟的任何函数都是 然后照常执行。接下来,F的调用者运行的任何延迟函数 是运行的,等等,直到任何由 执行goroutine。此时,程序被终止,并且 报告错误条件,包括要报告的参数值 惊恐这种终止序列称为恐慌

围棋博客

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

此页面收集在Go代码审查期间的常见注释,因此 一个单一的详细解释可以通过速记来引用。 这是一份常见错误的详细清单,不是风格指南

看。不要惊慌失措 用于正常的错误处理。使用错误和多个返回值

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

您的Go服务器程序正在同时处理100000个客户端。如果发生错误,报告并处理;始终检查错误。不要惊慌失措地让所有100000名客户崩溃。围棋包不应该惊慌失措


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

也许这应该是一个恐慌,但这是一个没有意义的问题,因为API不能在go1中更改。@JimB完全正确,但我相信这是否可以更改并不重要,但这一定是一个恐慌或错误。因为函数在错误使用时总是返回错误,并且错误文本对问题的描述足够好,程序员可以确定这是一个逻辑错误,在这种情况下,不需要通过编程将逻辑错误与其他错误区分开来。@rvillablanca也许您的Java代码可以在Golang中转换,是的,就我所知,这是一种常见的模式,询问组合输出的实现是否是最好的方式?在这里是没有用的,因为我们不能改变。API已设置,因此您可以通过测试来验证是否正确使用它,或者通过匹配错误字符串来使用它。