我是新手,发现错误处理非常冗长。我已经阅读了它的推理并且大多数都同意,但是有一些地方似乎有更多的代码来处理错误而不是实际工作。这是一个(人为的)例子,我在这里管道“Hello world!”进入猫并阅读和打印输出。基本上每一行都有三个来处理错误,我甚至都没有处理任何事情。
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
}
有没有一种惯用的,干净的方式来处理这个问题?我只是觉得我错过了什么。
答案 0 :(得分: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 代码详细。
答案 1 :(得分:0)
对于惯用语,请参阅peterSO
的答案,该答案开始涉及返回错误的主题,并且可以通过将错误与一些额外的与呼叫的上下文相关的信息包装起来来进一步采取这种做法。你的申请。
在某些操作中,迭代运行可能会保证在以下链接中使用一些非常有创意的示例更加通用,但正如我对该问题所评论的那样,这是一个不好的代码示例:Go — handling multiple errors elegantly?
无论如何,仅仅看一下你所拥有的例子,这只不过是主要的一次性,所以如果你只是想像在交互式python控制台中那样混乱,那么就这样对待它。 / p>
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))
}
答案 2 :(得分: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
}
答案 3 :(得分:-3)
在这种情况下,我通常会把它弄平一下。
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要容易得多。