【问题标题】:Golang Flag gets interpreted as first os.Args argumentGolang Flag 被解释为第一个 os.Args 参数
【发布时间】:2013-11-06 04:31:16
【问题描述】:

我想像这样运行我的程序:

go run launch.go http://example.com --m=2 --strat=par

"http://example.com" 被解释为第一个命令行参数,这没问题,但此后不解析标志并保持默认值。如果我这样说:

go run launch.go --m=2 --strat=par http://example.com

然后 "--m=2" 被解释为第一个参数(应该是 URL)。

我也可以完全删除 os.Args,但是我将只有可选标志,并且我希望一个(URL)是强制性的。

这是我的代码:

package main

import (
    "fmt"
    "webcrawler/crawler"
    "webcrawler/model"
    "webcrawler/urlutils"
    "os"
    "flag"
)

func main() {
    if len(os.Args) < 2 {
        log.Fatal("Url must be provided as first argument")
    }

    strategy := flag.String("strat", "par", "par for parallel OR seq for sequential crawling strategy")
    routineMultiplier := flag.Int("m", 1, "Goroutine multiplier. Default 1x logical CPUs. Only works in parallel strategy")

    page := model.NewBasePage(os.Args[1])
    urlutils.BASE_URL = os.Args[1]
    flag.Parse()
    pages := crawler.Crawl(&page, *strategy, *routineMultiplier)
    fmt.Printf("Crawled: %d\n", len(pages))
}

我很确定这应该是可能的,但我不知道怎么做。

编辑: 感谢 justinas 提供 flag.Args() 的提示。我现在像这样对其进行了改编,并且可以正常工作:

...
flag.Parse()

args := flag.Args()
    if len(args) != 1 {
        log.Fatal("Only one argument (URL) allowed.")
    }

page := model.NewBasePage(args[0])
...

【问题讨论】:

    标签: go command-line-arguments


    【解决方案1】:

    os.Argsflag 包一无所知,它包含所有命令行参数。试试flag.Args()(当然是在调用flag.Parse()之后)。

    【讨论】:

    • 似乎不适用于我的程序。如果标志前面有参数,它根本不会读取标志,无论您使用flag.Args()flag.Parse()
    【解决方案2】:

    作为后续,解析像

    这样的命令之后的标志
    runme init -m thisis
    

    您可以创建自己的标志集以跳过第一个值,例如

    var myValue string
    mySet := flag.NewFlagSet("",flag.ExitOnError)
    mySet.StringVar(&myValue,"m","mmmmm","something")
    mySet.Parse(os.Args[2:])
    

    【讨论】:

      【解决方案3】:

      这也让我感到困惑,因为我在我的应用程序的几个地方调用了flag.String/flag.Int64/etc,我不想到处传递一个新的flag.FlagSet

      // If a commandline app works like this: ./app subcommand -flag -flag2
      // `flag.Parse` won't parse anything after `subcommand`.
      // To still be able to use `flag.String/flag.Int64` etc without creating
      // a new `flag.FlagSet`, we need this hack to find the first arg that has a dash
      // so we know when to start parsing
      firstArgWithDash := 1
      for i := 1; i < len(os.Args); i++ {
          firstArgWithDash = i
      
          if len(os.Args[i]) > 0 && os.Args[i][0] == '-' {
              break
          }
      }
      
      flag.CommandLine.Parse(os.Args[firstArgWithDash:])
      

      我这样做的原因是因为flag.Parse 只是在后台调用flag.CommandLine.Parse(os.Args[1:])

      【讨论】:

        【解决方案4】:

        您可以检查 Arg 是否以“--”或“-”开头,并避免在循环中使用该 Arg。

        例如:

        for _, file := range os.Args[1:] {
            if strings.HasPrefix(file, "--") {
                continue
            }
            //do stuff
            }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2015-11-07
          • 2020-12-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-11-17
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多