Quelle est la manière idiomatique de quitter un programme avec un code d'erreur?
La documentation de Exit
indique "Le programme se termine immédiatement; les fonctions différées ne sont pas exécutées", et log.Fatal
appelle simplement Exit
. Pour des choses qui ne sont pas des erreurs odieuses, terminer le programme sans exécuter de fonctions différées semble extrême.
Suis-je censé transmettre un état indiquant une erreur, puis appeler Exit(1)
à un moment où je sais que je peux sortir en toute sécurité, toutes les fonctions différées ayant été exécutées?
Je fais quelque chose dans ce sens dans la plupart de mes paquets main
réels, de sorte que la convention return err
soit adoptée dès que possible et ait une terminaison appropriée:
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
}
Comme mentionné par fas, vous avez func Exit(exitcode int)
dans le package os.
Toutefois, si vous souhaitez que la fonction différée soit appliquée, vous pouvez toujours utiliser le mot clé defer
comme suit:
http://play.golang.org/p/U-hAS88Ug4
Vous effectuez toutes vos opérations, affectez une variable d'erreur et à la fin, lorsque tout est nettoyé, vous pouvez sortir en toute sécurité.
Sinon, vous pouvez également utiliser panic/recover: http://play.golang.org/p/903e76GnQ-
Lorsque vous avez une erreur, vous paniquez, terminez le nettoyage à l'endroit où vous l'attrapez.
En python, j'utilise couramment un motif converti en aller qui ressemble à ceci:
func run() int {
// here goes
// the code
return 1
}
func main() {
os.Exit(run())
}
Je pense que le moyen le plus clair de le faire est de placer exitCode
au sommet de main
, puis defer
fermant comme prochaine étape. Cela vous permet de changer exitCode
n'importe où dans main
, et sa dernière valeur sera renseignée avec:
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
}
Sortie:
Do some work
Do some cleanup
Program exited: status 1.
Go Playground https://play.golang.org/p/AMUR4m_A9Dw
Notez qu'un inconvénient important est que vous ne quittez pas le processus dès que vous définissez le code d'erreur.