web-dev-qa-db-fra.com

Quitter avec un code d'erreur en cours?

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?

36
dan

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
}
45
Gustavo Niemeyer

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.

3
creack

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())
}
1
user2424794

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.

0
Ben