Existe-t-il un moyen de définir que certains indicateurs sont obligatoires, ou dois-je vérifier leur présence par moi-même?
Le package flag
ne prend pas en charge les indicateurs obligatoires ou obligatoires (ce qui signifie que l'indicateur doit être spécifié explicitement).
Ce que vous pouvez faire, c'est utiliser des valeurs par défaut raisonnables pour (tous) les indicateurs. Et si un indicateur est quelque chose comme s'il n'y a pas de défaut sensible, vérifiez la valeur au début de votre application et arrêtez-vous avec un message d'erreur. Vous devriez quand même faire la validation de la valeur des indicateurs (pas seulement pour les indicateurs requis), donc cela ne devrait pas signifier de (gros) frais généraux, et c'est une bonne pratique en général.
Comme déjà mentionné , le package flag
ne fournit pas cette fonctionnalité directement et généralement vous pouvez (et devriez) être en mesure de fournir une valeur par défaut raisonnable. Pour les cas où vous n'avez besoin que d'un petit nombre d'arguments explicites (par exemple, un nom de fichier d'entrée et de sortie), vous pouvez utiliser des arguments de position (par exemple après flag.Parse()
vérifiez que flag.NArg()==2
puis input, output := flag.Arg(0), flag.Arg(1)
).
Si toutefois, vous avez un cas où cela n'est pas raisonnable; dites quelques drapeaux entiers que vous souhaitez accepter dans n'importe quel ordre, où toute valeur entière est raisonnable, mais aucune valeur par défaut ne l'est. Ensuite, vous pouvez utiliser la fonction flag.Visit
pour vérifier si les indicateurs qui vous intéressent ont été explicitement définis ou non. Je pense que c'est la seule façon de savoir si un indicateur a été explicitement défini sur sa valeur par défaut (sans compter un type flag.Value
Personnalisé avec une implémentation Set
qui a gardé son état).
Par exemple, peut-être quelque chose comme:
required := []string{"b", "s"}
flag.Parse()
seen := make(map[string]bool)
flag.Visit(func(f *flag.Flag) { seen[f.Name] = true })
for _, req := range required {
if !seen[req] {
// or possibly use `log.Fatalf` instead of:
fmt.Fprintf(os.Stderr, "missing required -%s argument/flag\n", req)
os.Exit(2) // the same exit code flag.Parse uses
}
}
Cela produirait une erreur si l'indicateur "-b" ou "-s" n'était pas explicitement défini.
go-flags
vous permet de déclarer à la fois les drapeaux requis et les arguments positionnels requis:
var opts struct {
Flag string `short:"f" required:"true" name:"a flag"`
Args struct {
First string `positional-arg-name:"first arg"`
Sencond string `positional-arg-name:"second arg"`
} `positional-args:"true" required:"2"`
}
args, err := flags.Parse(&opts)
J'aime github.com/jessevdk/go-flags
package à utiliser en CLI. Il s'agit de l'attribut required
, pour définir l'indicateur obligatoire. Comme ça:
var opts struct {
...
// Example of a required flag
Name string `short:"n" long:"name" description:"A name" required:"true"`
...
}
Si vous avez un chemin de drapeau, vérifiez simplement si * chemin contient une valeur
var path = flag.String("f", "", "/path/to/access.log")
flag.Parse()
if *path == "" {
usage()
os.Exit(1)
}
Je suis d'accord avec cette solution mais, dans mon cas, les valeurs par défaut sont généralement des valeurs d'environnement. Par exemple,
dsn := flag.String("dsn", os.Getenv("MYSQL_DSN"), "data source name")
Et dans ce cas, je veux vérifier si les valeurs sont définies à partir de l'invocation (généralement le développement local) ou de l'environnement var (environnement prod).
Donc, avec quelques modifications mineures, cela a fonctionné pour mon cas.
Utiliser flag.VisitAll pour vérifier la valeur de tous les indicateurs.
required := []string{"b", "s"}
flag.Parse()
seen := make(map[string]bool)
flag.VisitAll(func(f *flag.Flag) {
if f.Value.String() != "" {
seen[f.Name] = true
}
})
for _, req := range required {
if !seen[req] {
// or possibly use `log.Fatalf` instead of:
fmt.Fprintf(os.Stderr, "missing required -%s argument/flag\n", req)
os.Exit(2) // the same exit code flag.Parse uses
}
}