Выйти с кодом ошибки в go?
Какой идиоматический способ выхода из программы с каким-нибудь кодом ошибки?
Документация для Exit
гласит: "Программа немедленно завершается; отложенные функции не запускаются.", И log.Fatal
просто вызывает Exit
. Для вещей, которые не являются отвратительными ошибками, завершение программы без запуска отложенных функций кажется крайним.
Должен ли я обойти какое-либо состояние, которое указывает на то, что произошла ошибка, и затем вызвать Exit(1)
в какой-то момент, когда я знаю, что могу безопасно выйти из системы, когда все отложенные функции были запущены?
Ответы
Ответ 1
Я делаю что-то подобное в большинстве моих реальных пакетов 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
}
Ответ 2
Как указано в fas, у вас есть func Exit(exitcode int)
из пакета os.
Тем не менее, если вам нужно defered функцию, которая будет применяться, вы всегда можете использовать defer
ключевое слово, как это:
http://play.golang.org/p/U-hAS88Ug4
Вы выполняете все свои действия, воздействуете на переменную ошибки и в самом конце, когда все вычищено, вы можете безопасно выйти.
В противном случае вы также можете использовать панику /recovery: http://play.golang.org/p/903e76GnQ-
Когда у вас есть ошибка, вы паникуете, завершаете очистку, где вы ее ловите (восстанавливаете).
Ответ 3
В python я обычно использую шаблон, который преобразуется в go, выглядит так:
func run() int {
// here goes
// the code
return 1
}
func main() {
os.Exit(run())
}
Ответ 4
Я думаю, что наиболее ясный способ сделать это - установить exitCode
в верхней части main
, а затем закрыть defer
в качестве следующего шага. Это позволяет вам изменить exitCode
в любом месте main
, и его последнее значение будет закрыто с помощью:
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 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.
Go Playgroundhttps://play.golang.org/p/AMUR4m_A9Dw
Обратите внимание, что важным недостатком этого является то, что вы не выходите из процесса, как только вы установите код ошибки.
Ответ 5
Да, на самом деле. Пакет os предоставляет это.
package main
import "os"
func main() {
os.Exit(1)
}
http://golang.org/pkg/os/#Exit
Изменить: похоже, что вы знаете о выходе. В этой статье дается обзор Panic, который позволит отложить функции перед возвращением. Использование этого в сочетании с выходом может быть тем, что вы ищете. http://blog.golang.org/defer-panic-and-recover