douqiu0796 2015-03-18 14:51
浏览 77
已采纳

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

I'm having a problem using Ubuntu 14.04 and executing diff on the command line. Look at the following Go code:

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))
}

If i execute this using go run test.go i get the following error:

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

So something is going wrong with diff and it's returning 1 as its exit code. Only the diff command seems to throw an error. If i use the cat or wc command, the code runs fine.

Any ideas why diff doesn't work here but other commands do?

  • 写回答

1条回答 默认 最新

  • dsfgds4215 2015-03-18 15:16
    关注

    When you run a program with exec, you get an error if the exit code was not 0. From the doc:

    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.

    So what happens here is that diff returns an error when the files are different, yet you treat it like a runtime error. Just change your code to reflect that it isn't. It's possible by checking the error.

    e.g. something like this:

        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)
            }
        }
    

    Also, I've changed it get CombinedOutput, so if any diff specific errors occured, you'll see stderr as well.

    Note that you'll get a "valid" error even if one of the files doesn't exist. So you can check the ExitError's exit code by doing something like this:

        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)
                }
            }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 ogg dd trandata 报错
  • ¥15 高缺失率数据如何选择填充方式
  • ¥50 potsgresql15备份问题
  • ¥15 Mac系统vs code使用phpstudy如何配置debug来调试php
  • ¥15 目前主流的音乐软件,像网易云音乐,QQ音乐他们的前端和后台部分是用的什么技术实现的?求解!
  • ¥60 pb数据库修改与连接
  • ¥15 spss统计中二分类变量和有序变量的相关性分析可以用kendall相关分析吗?
  • ¥15 拟通过pc下指令到安卓系统,如果追求响应速度,尽可能无延迟,是不是用安卓模拟器会优于实体的安卓手机?如果是,可以快多少毫秒?
  • ¥20 神经网络Sequential name=sequential, built=False
  • ¥16 Qphython 用xlrd读取excel报错