【问题标题】:getopt-like behavior in GoGo 中类似 getopt 的行为
【发布时间】:2010-12-15 09:56:51
【问题描述】:

如何很好地解析程序参数列表并在 Go 中自动处理“--help”和/或“--version”(例如“program [-d value] [--abc] [FILE1]”)?

【问题讨论】:

  • 2019:github.com/rsc/getopt 似乎是一个简单的选择:见my answer below

标签: go


【解决方案1】:

Google 已经创建了一个 getopt 包 (import "github.com/pborman/getopt"),它提供了更标准的命令行解析(与“标志”包相比)。

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!

【讨论】:

  • 糟糕,我错了。该软件包由 Google 员工编写,Google 拥有版权。
  • 新手问题 - 这会干扰位置参数吗?我假设不是。我需要做更多的阅读。
【解决方案2】:

使用“标志”包:http://golang.org/pkg/flag/。但是,它不执行双破折号参数。还没有任何东西可以完全模仿 GNU getopt 行为。

【讨论】:

  • 是时候有人写一篇了。它已经发布了一整天了。
  • @Kinopiko:看看源代码仓库 misc/emacs 目录下的 go-mode.el。
  • 这里是一个使用命令行标志的示例的链接:golang.org/doc/go_tutorial.html#tmp_53(Go 教程中的“Echo”示例)
【解决方案3】:

在“命令行 UI”部分,您有几个库能够解析 getopt-long parameters

我用 Go1.0.2 试过了:

例子:

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
}

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

【讨论】:

    【解决方案4】:

    go-flags很完整,BSD授权,有明确的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)
    }
    

    【讨论】:

    • go-flags 非常完整,并且还具有我想要的子命令功能。但是文档很难理解。我建议阅读示例代码+参考其文档将是最好的。 (您指向的示例链接非常有用。)
    【解决方案5】:

    另一个选项是Kingping,它支持您期望从现代命令行解析库中获得的所有标准好东西。它具有多种格式、子命令、要求、类型、默认值等的--help。它还在开发中。这里的其他建议似乎有一段时间没有更新了。

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

    还有--help 输出:

    $ 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.
    

    【讨论】:

      【解决方案6】:

      我只是为你做的:

      package main
      
      import (
        "fmt";
        "os"
      )
      
      func main() {
        for i, arg := range os.Args {
          if arg == "-help" {
            fmt.Printf ("I need somebody\n")
          }else if arg == "-version" {
            fmt.Printf ("Version Zero\n")
          } else {
            fmt.Printf("arg %d: %s\n", i, os.Args[i])
          }
        }
      }
      

      另见https://play.golang.org/p/XtNXG-DhLI

      测试:

      $ ./8.out -help -version 猴子业务 我需要一个人 零版本 参数 3:猴子 参数 4:商业

      【讨论】:

      • 此代码不支持标志参数(如 OP 的 -d value)或默认值;如果程序员自己动手,他们不太可能满足用户的期望(比如--key value--key=value 的等价性)。手工滚动 --help 使得生成制表符补全变得困难,并且需要手动维护空间上不同的代码。实际代码可能应该一方面将 Args 划分为标志及其值,另一方面将非标志 args 划分为。当一个新手就参数解析等棘手但基本的事情寻求指导时,正确的答案不是“自己动手”。
      【解决方案7】:

      我认为你想要的是 docopt。我会推荐你​​to an earlier answer我发布的详细信息。

      【讨论】:

        【解决方案8】:

        作为一个简单的库,您从 2017 年 8 月开始拥有 github.com/rsc/getopt

        要使用,请像往常一样使用包标志定义标志。然后通过调用getopt.Alias 引入任何别名:

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

        或调用getopt.Aliases 定义别名列表:

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

        还有:

        一般来说,Go 标志解析对于新程序来说是首选,因为它对用于调用标志的破折号数量没有那么迂腐(你可以写 -verbose--verbose,程序并不关心)。

        此包旨在用于由于遗留原因,准确使用 getopt(3) 语法很重要的情况,例如在 Go 中重写已经使用 @987654331 的现有工具时@。

        【讨论】:

          【解决方案9】:

          可以简单地使用 Golang 自己的库“flag”。

          它有很多代码可以在 GoLang 中创建类似 CLI 的应用程序。例如:

          srcDir := flag.String("srcDir", "", "Source directory of the input csv file.")
          

          上述标志库的 String 方法需要一个来自命令提示符的参数。

          转至https://golang.org/pkg/flag/ 了解更多信息。

          快乐学习...

          【讨论】:

            猜你喜欢
            • 2014-05-25
            • 1970-01-01
            • 2023-03-31
            • 1970-01-01
            • 1970-01-01
            • 2021-07-13
            • 1970-01-01
            • 1970-01-01
            • 2010-10-19
            相关资源
            最近更新 更多