11

我是新手,发现错误处理非常冗长。我已经阅读了它的推理并且大多同意,但是在某些地方,处理错误的代码似乎比实际工作要多。这是一个(人为的)示例,我在其中管道“Hello world!” 进入 cat 并读取并打印输出。基本上每一行都有另外三个来处理错误,我什至什么都没有处理。

package main

import "fmt"
import "io"
import "io/ioutil"
import "os/exec"


func main() {
    cmd := exec.Command("cat", "-")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        return
    }
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return
    }
    err = cmd.Start()
    if err != nil {
        return
    }
    _, err = io.WriteString(stdin, "Hello world!")
    if err != nil {
        return
    }
    err = stdin.Close();
    if err != nil {
        return
    }
    output, err := ioutil.ReadAll(stdout)
    if err != nil {
        return
    }
    fmt.Println(string(output))
    return
}

有没有一种惯用的、干净的方式来处理这个问题?我只是觉得我错过了一些东西。

4

4 回答 4

7

显然,我们必须处理任何错误;我们不能忽视它们。

例如,试图使示例不那么人工,

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "os"
    "os/exec"
)

func piping(input string) (string, error) {
    cmd := exec.Command("cat", "-")
    stdin, err := cmd.StdinPipe()
    if err != nil {
        return "", err
    }
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        return "", err
    }
    err = cmd.Start()
    if err != nil {
        return "", err
    }
    _, err = io.WriteString(stdin, input)
    if err != nil {
        return "", err
    }
    err = stdin.Close()
    if err != nil {
        return "", err
    }
    all, err := ioutil.ReadAll(stdout)
    output := string(all)
    if err != nil {
        return output, err
    }
    return output, nil
}

func main() {
    in := "Hello world!"
    fmt.Println(in)
    out, err := piping(in)
    if err != nil {
        fmt.Println(err)
        os.Exit(1)
    }
    fmt.Println(out)
}

输出:

Hello world!
Hello world!

错误处理和 Go

在 Go 中,错误处理很重要。该语言的设计和约定鼓励您在错误发生的地方明确检查错误(与其他语言中抛出异常并有时捕获它们的约定不同)。在某些情况下,这会使 Go 代码变得冗长。

于 2013-04-20T23:56:18.053 回答
0

我只是在 Go 中写了几百行,所以我没有标题表示任何惯用的方式。但是,在重复调用和检查错误步骤的情况下,如果我恢复逻辑,我发现代码更容易编写和阅读:而不是检查退出条件(错误!= nil) ,我检查继续的条件( err == nil ),如下所示。
如果您有一种独特的方式来处理错误,无论是哪个错误,例如返回调用者或​​打印/记录它,都可以做到这一点。这种方法的缺点是您不能使用 := 隐式声明变量,因为它们将具有分配它们的 if 块的范围。

func main() {
    var output []byte
    var stdin io.WriteCloser 
    var stdout io.Reader 

    cmd := exec.Command("cat", "-")

    stdin, err := cmd.StdinPipe()

    if err == nil {
      stdout, err = cmd.StdoutPipe()
    }

    if err == nil {
      err = cmd.Start()
    }

    if err == nil {
      _, err = io.WriteString(stdin, "Hello world!")
    }

    if err == nil {
    output, err = ioutil.ReadAll(stdout)
    } 

    if err == nil {
     err = stdin.Close();
    }

    if err == nil {
            fmt.Println(string(output))
    } else {
         fmt.Println(string(err.Error())) // Error handling goes here
    }

    return
}
于 2014-04-08T15:44:14.403 回答
0

对于惯用的,请参阅peterSO开始涉及返回错误主题的答案,并且可以通过使用与应用程序中调用上下文相关的一些额外信息来包装错误来进一步采取行动。

在某些情况下,对操作的迭代运行可能需要通过以下链接中的一些非常有创意的示例进行更通用的处理,但正如我对这个问题的评论,这是一个糟糕的代码示例来检查:Go — 优雅地处理多个错误?

无论如何,仅查看您拥有的示例,这只不过是一次性的,因此,如果您只是想像在交互式 python 控制台中那样搞乱,请像这样对待它。

package main

import (
    "fmt"
    "io"
    "io/ioutil"
    "os/exec"
)

func main() {
    cmd := exec.Command("cat", "-")
    stdin, _ := cmd.StdinPipe()
    stdout, _ := cmd.StdoutPipe()

    cmd.Start()
    io.WriteString(stdin, "Hello world!")

    stdin.Close();
    output, _ := ioutil.ReadAll(stdout)

    fmt.Println(string(output))
}
于 2013-04-21T01:06:00.643 回答
-2

在这种情况下,我通常只是把它弄平一点。

func myFunc() (err error) {
    cmd := exec.Command("cat", "-")

    stdin,  err := cmd.StdinPipe();                  if err != nil { return }
    stdout, err := cmd.StdoutPipe();                 if err != nil { return }

       err  = cmd.Start();                           if err != nil { return }
    _, err  = io.WriteString(stdin, "Hello world!"); if err != nil { return }
       err  = stdin.Close();                         if err != nil { return }
    o, err := ioutil.ReadAll(stdout);                if err != nil { return }

    fmt.Println(string(o))
    return
}

仍然丑陋,但至少它不那么垂直,而且我们得到了一些对齐。

我不能说这符合任何约定,但它更容易阅读 IMO。

于 2013-04-21T01:19:07.277 回答