Exit with error code in go?

huangapple go评论83阅读模式
英文:

Exit with error code in go?

问题

在程序中以某个错误代码退出的惯用方式是什么?

Exit 的文档中写道:“程序立即终止;延迟函数不会被执行。”而 log.Fatal 只是调用了 Exit。对于不是严重错误的情况,终止程序而不运行延迟函数似乎过于极端。

我应该传递一些状态来指示发生了错误,然后在我知道可以安全退出且所有延迟函数都已运行的某个点上调用 Exit(1) 吗?

英文:

What's the idiomatic way to exit a program with some error code?

The documentation for Exit says "The program terminates immediately; deferred functions are not run.", and log.Fatal just calls Exit. For things that aren't heinous errors, terminating the program without running deferred functions seems extreme.

Am I supposed to pass around some state that indicate that there's been an error, and then call Exit(1) at some point where I know that I can exit safely, with all deferred functions having been run?

答案1

得分: 121

我在大多数真实的main包中都会按照这样的方式进行操作,以便尽早采用return err的约定,并进行适当的终止:

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

func run() error {
    err := something()
    if err != nil {
        return err
    }
    // 其他操作
}

这段代码的作用是在main函数中调用run函数,并在run函数返回错误时打印错误信息并退出程序。

英文:

I do something along these lines in most of my real main packages, so that the return err convention is adopted as soon as possible, and has a proper termination:

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
}

答案2

得分: 11

在Python中,我通常使用一种模式,转换为Go语言后如下所示:

func run() int {
    // 这里是代码
    return 1
}

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

希望这个翻译对你有帮助!

英文:

In Python I commonly use a pattern, which being converted to Go looks like this:

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

	return 1
}

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

答案3

得分: 6

我认为最清晰的方法是在main函数的开头设置exitCode,然后在下一步使用defer关闭。这样你可以在main函数的任何地方更改exitCode,并且它的最后一个值将被用于退出:

package main

import (
    "fmt"
    "os"
)

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

    // 做任何事情,包括延迟更多的函数

    defer func() {
        fmt.Printf("做一些清理工作\n")
    }()

    func() {
        fmt.Printf("做一些工作\n")
    }()

    // 但是假设出现了错误
    exitCode = 1

    // 如果需要,可以继续做更多的工作/清理

    // 最后,os.Exit将使用exitCode的最后一个值被调用
}

输出:

做一些工作
做一些清理工作

程序退出:状态 1。

请注意,这种方法的一个重要缺点是,一旦设置了错误代码,你不会立即退出进程。

英文:

I think the most clear way to do it is to set the exitCode at the top of main, then defer closing as the next step. That lets you change exitCode anywhere in main, and it's last value will be exited with:

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
}

Output:

Do some work
Do some cleanup

Program exited: status 1.

Go Playgroundhttps://play.golang.org/p/AMUR4m_A9Dw

Note that an important disadvantage of this is that you don't exit the process as soon as you set the error code.

答案4

得分: 3

如fas所提到的,你可以使用os包中的func Exit(exitcode int)函数。

然而,如果你需要延迟执行的函数,你可以使用defer关键字,像这样:

http://play.golang.org/p/U-hAS88Ug4

你执行所有的操作,影响一个错误变量,在最后,当所有事情都清理完毕时,你可以安全地退出。

另外,你也可以使用panic/recover:

http://play.golang.org/p/903e76GnQ-

当你遇到错误时,你会触发panic,然后在捕获(recover)它的地方进行清理。

英文:

As mentioned by fas, you have func Exit(exitcode int) from the os package.

However, if you need the defered function to be applied, you always can use the defer keyword like this:

http://play.golang.org/p/U-hAS88Ug4

You perform all your operation, affect a error variable and at the very end, when everything is cleaned up, you can exit safely.

Otherwise, you could also use panic/recover:
http://play.golang.org/p/903e76GnQ-

When you have an error, you panic, end you cleanup where you catch (recover) it.

答案5

得分: 0

是的,实际上是这样的。os包提供了这个功能。

package main

import "os"

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

你可以在这里查看更多关于os.Exit的信息:http://golang.org/pkg/os/#Exit

编辑:看起来你已经知道了Exit。这篇文章概述了Panic,它可以在返回之前运行延迟函数。结合使用PanicExit可能是你正在寻找的。你可以在这里阅读更多信息:http://blog.golang.org/defer-panic-and-recover

英文:

Yes, actually. The os package provides this.

package main

import "os"

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

http://golang.org/pkg/os/#Exit

Edit: so it looks like you know of Exit. This article gives an overview of Panic which will let deferred functions run before returning. Using this in conjunction with an exit may be what you're looking for. http://blog.golang.org/defer-panic-and-recover

答案6

得分: 0

另一种我遵循的好方法是:

if err != nil {
    // log.Fatal会打印错误消息,并内部调用System.exit(1)以终止程序
    log.Fatal("致命错误消息")
}
英文:

Another good way I follow is:

if err != nil {
    // log.Fatal will print the error message and will internally call System.exit(1) so the program will terminate
	log.Fatal("fatal error message")
}

huangapple
  • 本文由 发表于 2013年9月24日 00:09:56
  • 转载请务必保留本文链接:https://go.coder-hub.com/18963984.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定