getopt-like behavior in Go

前端 未结 9 706
南笙
南笙 2021-02-07 11:33

How do I nicely parse a list of program parameters and automate handling \"--help\" and/or \"--version\" (such as \"program [-d value] [--abc] [FILE1]\") in Go?

相关标签:
9条回答
  • 2021-02-07 11:50

    go-flags is very complete, BSD licensed, and has a clear example.

    var opts struct {
          DSomething string `short:"d" description:"Whatever this is" required:"true"`
          ABC bool `long:"abc" description:"Something"`
    }
    
    fileArgs, err := flags.Parse(&opts)
    
    if err != nil {
        os.Exit(1)
    }
    
    0 讨论(0)
  • 2021-02-07 11:51

    Another option is Kingping which provides support for all the standard goodies you have come to expect from a modern command line parsing library. It has --help in multiple formats, sub-commands, requirements, types, defaults, etc. It's also still under development. It seems like the other suggestions here haven't been updated in a while.

    package main
    
    import (
      "os"
      "strings"
      "gopkg.in/alecthomas/kingpin.v2"
    )
    
    var (
      app      = kingpin.New("chat", "A command-line chat application.")
      debug    = app.Flag("debug", "Enable debug mode.").Bool()
      serverIP = app.Flag("server", "Server address.").Default("127.0.0.1").IP()
    
      register     = app.Command("register", "Register a new user.")
      registerNick = register.Arg("nick", "Nickname for user.").Required().String()
      registerName = register.Arg("name", "Name of user.").Required().String()
    
      post        = app.Command("post", "Post a message to a channel.")
      postImage   = post.Flag("image", "Image to post.").File()
      postChannel = post.Arg("channel", "Channel to post to.").Required().String()
      postText    = post.Arg("text", "Text to post.").Strings()
    )
    
    func main() {
      switch kingpin.MustParse(app.Parse(os.Args[1:])) {
      // Register user
      case register.FullCommand():
        println(*registerNick)
    
      // Post message
      case post.FullCommand():
        if *postImage != nil {
        }
        text := strings.Join(*postText, " ")
        println("Post:", text)
      }
    }
    

    And the --help output:

    $ chat --help
    usage: chat [<flags>] <command> [<flags>] [<args> ...]
    
    A command-line chat application.
    
    Flags:
      --help              Show help.
      --debug             Enable debug mode.
      --server=127.0.0.1  Server address.
    
    Commands:
      help [<command>]
        Show help for a command.
    
      register <nick> <name>
        Register a new user.
    
      post [<flags>] <channel> [<text>]
        Post a message to a channel.
    
    0 讨论(0)
  • 2021-02-07 11:55

    From the section "Command Line UI", you have several libraries able to parse getopt-long parameters.

    I tried, with a Go1.0.2:

    • the code.google.com/p/opts-go (See its documentation), which isn't quite operational.
    • the github.com/droundy/goopt (See its documentation), which has a complete set of examples.

    Example:

    package main
    
    import (
        "fmt"
        goopt "github.com/droundy/goopt"
    )
    
    func main() {
        fmt.Println("flag")
        goopt.NoArg([]string{"--abc"}, "abc param, no value", noabc)
    
        goopt.Description = func() string {
            return "Example program for using the goopt flag library."
        }
        goopt.Version = "1.0"
        goopt.Summary = "goopt demonstration program"
        goopt.Parse(nil)
    }
    
    func noabc() error {
        fmt.Println("You should have an --abc parameter")
        return nil
    }
    

    Other default parameters provided with goopt:

     --help               Display the generated help message (calls Help())
     --create-manpage     Display a manpage generated by the goopt library (uses Author, Suite, etc)
     --list-options       List all known flags
    
    0 讨论(0)
  • 2021-02-07 11:55

    As a simple library, you have since August 2017 github.com/rsc/getopt

    To use, define flags as usual with package flag. Then introduce any aliases by calling getopt.Alias:

    getopt.Alias("v", "verbose")
    

    Or call getopt.Aliases to define a list of aliases:

    getopt.Aliases(
        "v", "verbose",
        "x", "xylophone",
    )
    

    And:

    In general Go flag parsing is preferred for new programs, because it is not as pedantic about the number of dashes used to invoke a flag (you can write -verbose or --verbose, and the program does not care).

    This package is meant to be used in situations where, for legacy reasons, it is important to use exactly getopt(3) syntax, such as when rewriting in Go an existing tool that already uses getopt(3).

    0 讨论(0)
  • 2021-02-07 11:58

    Google has created a getopt package (import "github.com/pborman/getopt") which provides the more standard command line parsing (vs the 'flag' package).

    package main
    
    import (
        "fmt"
        "os"
        "github.com/pborman/getopt"
    )
    
    func main() {
        optName := getopt.StringLong("name", 'n', "", "Your name")
        optHelp := getopt.BoolLong("help", 0, "Help")
        getopt.Parse()
    
        if *optHelp {
            getopt.Usage()
            os.Exit(0)
        }
    
        fmt.Println("Hello " + *optName + "!")
    }
    

     

    $ ./hello --help
    Usage: hello [--help] [-n value] [parameters ...]
         --help        Help
     -n, --name=value  Your name
    
    $ ./hello --name Bob
    Hello Bob!
    
    0 讨论(0)
  • 2021-02-07 11:58

    I think what you want is docopt. I'll just refer you to an earlier answer I posted for the details.

    0 讨论(0)
提交回复
热议问题