如何使用 Go 在命令行上执行 diff?

How to execute diff on the command line using Go?

我在使用 Ubuntu 14.04 和在命令行上执行 diff 时遇到问题。看下面的 Go 代码:

package main

import "fmt"
import "log"
import "os/exec"

func main() {
    output, err := exec.Command("diff", "-u", "/tmp/revision-1", "/tmp/revision-4").Output()
    if err != nil {
        log.Fatalln(err)
    }

    fmt.Println(string(output))
}

如果我使用 go run test.go 执行此操作,我会收到以下错误:

2015/03/18 14:39:25 exit status 1
exit status 1

所以 diff 出了点问题,它返回 1 作为退出代码。只有 diff 命令似乎会引发错误。如果我使用 catwc 命令,代码运行正常。

知道为什么 diff 在这里不起作用但其他命令可以吗?

当您 运行 使用 exec 的程序时,如果退出代码不是 0,您会收到错误消息。来自文档:

The returned error is nil if the command runs, has no problems copying stdin, stdout, and stderr, and exits with a zero exit status.

If the command fails to run or doesn't complete successfully, the error is of type *ExitError. Other error types may be returned for I/O problems.

所以这里发生的是 diff returns 当文件不同时出现错误,但您将其视为 运行 时间错误。只需更改您的代码以反映它不是。通过检查错误是可能的。

例如像这样:

    output, err := exec.Command("diff", "-u", "/tmp/revision-1", "/tmp/revision-4").CombinedOutput()
    if err != nil {
           
        switch err.(type) {
        case *exec.ExitError:
            // this is just an exit code error, no worries
            // do nothing

        default: //couldnt run diff
            log.Fatal(err)
        }
    }

此外,我已将其更改为 CombinedOutput,因此如果发生任何特定于 diff 的错误,您也会看到 stderr。

注意即使其中一个文件不存在,您也会收到“有效”错误。因此,您可以通过执行以下操作来检查 ExitError 的退出代码:

    switch e := err.(type) {
    case *exec.ExitError:

        // we can check the actual error code. This is not platform portable 
        if status, ok := e.Sys().(syscall.WaitStatus); ok {
            // exit code 1 means theres a difference and is not an error
            if status.ExitStatus() != 1 { 
                log.Fatal(err)
            }
        }