1

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
Sergei Basharov
  • 51,276
  • 73
  • 200
  • 335

2 Answers2

2

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")
    }
}
Kare Nuorteva
  • 1,046
  • 11
  • 12
1

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)
    }
}

Reference

Community
  • 1
  • 1
John S Perayil
  • 6,001
  • 1
  • 32
  • 47
  • Note that there are reserved flags you cannot overwrite. If I recall, "build" and "help" are two such flags. "Run" may be another one. – eduncan911 Jan 12 '17 at 07:20