I know I can define flags like this:
initPtr := flag.String("init", "config.json", "Initialize with config filename")
Which I will call like this:
myapp --init=myconfig.json
I wonder though if I can define something like commands so that to call the app like this?
myapp init --filename=myconfig.json
myapp check --filename=myconfig.json
myapp run
Yes, you can.
Take a look at https://golang.org/pkg/flag/ for FlagSet documentation.
And for a working example: https://github.com/constabulary/gb/blob/master/cmd/gb/main.go
And an example as requested by miltonb:
% go run flagset.go init --filename=foo.json foo bar
init foo.json [foo bar]
% go run flagset.go check --filename=bar.json 1 2 3
check bar.json [1 2 3]
% go run flagset.go run
run
% cat flagset.go
package main
import (
"flag"
"fmt"
"os"
)
func main() {
init := flag.NewFlagSet("init", flag.ExitOnError)
initFile := init.String("filename", "myconfig.json", "configuration file")
check := flag.NewFlagSet("check", flag.ExitOnError)
checkFile := check.String("filename", "myconfig.json", "configuration file")
if len(os.Args) <= 1 {
flag.Usage()
os.Exit(1)
}
switch os.Args[1] {
case "init":
if err := init.Parse(os.Args[2:]); err == nil {
fmt.Println("init", *initFile, init.Args())
}
case "check":
if err := check.Parse(os.Args[2:]); err == nil {
fmt.Println("check", *checkFile, check.Args())
}
case "run":
fmt.Println("run")
}
}
You can do that using a combination of command line arguments and flags.
Eg.
configFilePtr := flag.String("filename", "", "Config Filename")
flag.Parse()
n := len(os.Args)
if n > 1 {
switch os.Args[1] {
case "init":
initApp(*configFilePtr)
case "check":
checkApp(*configFilePtr)
case "run":
runApp()
}
}
Another option is using something like spf13's cobra
.
Update :
If you require the use of different flags as per command you can use a FlagSet as mentioned in Kare Nuorteva
's answer.
Eg.
f1 := flag.NewFlagSet("f1", flag.ContinueOnError)
silent := f1.Bool("silent", false, "")
f2 := flag.NewFlagSet("f2", flag.ContinueOnError)
loud := f2.Bool("loud", false, "")
switch os.Args[1] {
case "apply":
if err := f1.Parse(os.Args[2:]); err == nil {
fmt.Println("apply", *silent)
}
case "reset":
if err := f2.Parse(os.Args[2:]); err == nil {
fmt.Println("reset", *loud)
}
}