Error handling 是否退出并在go中显示错误代码?

Error handling 是否退出并在go中显示错误代码?,error-handling,go,exit,Error Handling,Go,Exit,退出带有错误代码的程序的惯用方法是什么 Exit的文档说明“程序立即终止;延迟函数不运行。”,而log.Fatal只调用Exit。对于那些不是令人发指的错误,在不运行延迟函数的情况下终止程序似乎是极端的 我是否应该传递一些表示出现错误的状态,然后在我知道可以安全退出的某个点调用Exit(1),所有延迟函数都已运行?是的,实际上。操作系统包提供了这一点 package main import "os" func main() { os.Exit(1) } 编辑:看来你知道退出了。本

退出带有错误代码的程序的惯用方法是什么

Exit
的文档说明“程序立即终止;延迟函数不运行。”,而
log.Fatal
只调用
Exit
。对于那些不是令人发指的错误,在不运行延迟函数的情况下终止程序似乎是极端的


我是否应该传递一些表示出现错误的状态,然后在我知道可以安全退出的某个点调用
Exit(1)
,所有延迟函数都已运行?

是的,实际上。操作系统包提供了这一点

package main

import "os"

func main() {
    os.Exit(1)
}


编辑:看来你知道退出了。本文概述了Panic,它可以让延迟函数在返回之前运行。将其与出口结合使用可能是您想要的

如fas所述,您已经从操作系统包中退出了
func(exitcode int)

但是,如果您需要应用延迟功能,则始终可以使用以下
defer
关键字:

func run() int {
    // here goes
    // the code

    return 1
}

func main() {
    os.Exit(run())
}

您执行了所有操作,影响了一个错误变量,最后,当一切都被清理干净时,您可以安全地退出

否则,您也可以使用紧急/恢复:


当出现错误时,您会惊慌失措,在捕获(恢复)错误的地方结束清理。

我在大多数real
main
软件包中都遵循这些原则,以便尽快采用
return err
约定,并具有适当的终止:

func main() {
    if err := run(); err != nil {
        fmt.Fprintf(os.Stderr, "error: %v\n", err)
        os.Exit(1)
    }
}

func run() error {
    err := something()
    if err != nil {
        return err
    }
    // etc
}

在python中,我通常使用转换为go的模式,如下所示:

func run() int {
    // here goes
    // the code

    return 1
}

func main() {
    os.Exit(run())
}

我认为最清楚的方法是将
exitCode
设置在
main
的顶部,然后将
defer
关闭作为下一步。您可以在
main
中的任何位置更改
exitCode
,它的最后一个值将以以下方式退出:

package main

import (
    "fmt"
    "os"
)

func main() {
    exitCode := 0
    defer func() { os.Exit(exitCode) }()

    // Do whatever, including deferring more functions

    defer func() {
        fmt.Printf("Do some cleanup\n")
    }()

    func() {
        fmt.Printf("Do some work\n")
    }()

    // But let's say something went wrong
    exitCode = 1

    // Do even more work/cleanup if you want

    // At the end, os.Exit will be called with the last value of exitCode
}
输出:

Do some work
Do some cleanup

Program exited: status 1.
去操场


请注意,这样做的一个重要缺点是,您不会在设置错误代码后立即退出流程。

如果全局变量状态默认为
clean
,并在非致命错误时设置为
dirty
,该怎么办。在退出
main()
之前,可以检查该变量。不是很好,但在某些情况下,这可能是最简单的解决方案。(我很高兴评论不能通过投票:))是的,基本上我就是这么做的。我发现它不雅观,因为我必须避免在main中延迟任何内容(因为我仍然调用Exit(1)来设置返回代码,并且不想杀死延迟的fn),所以我将以前的main(只有三行,其中一行是defer)插入到一个函数中。我希望有人能有更好的办法。到目前为止,有一个人回复了os.Exit,当我在帖子中评论我引用了os.Exit文档时,他们的回复被删除了,现在有另一个答案指向os.Exit。我很确定@dan知道这一点。也许我读错了,或者他编辑了,但我认为他在谈论其他东西。我想我理解你在第一种方法中的意思,但这个例子让我有点困惑。为什么要推迟fct1()和fct2()?这意味着它们将以相反的顺序执行!看来你打算还是不愿意?我认为这是最好的解决办法。您可以从
run()
方法返回一个错误,并让
main()
处理它,而不考虑它是否合适。不考虑这个问题,但在编写更多的Go代码后,我认为(Gustavo Niemeyer的回答)基本上在所有情况下都更清晰、更易于使用。跟踪函数调用比跟踪延迟容易得多。测试此代码的最佳方法是什么?在函数测试中运行二进制文件。