Golang Flag被解释为第一个os.Args参数

时间:2013-10-27 10:51:01

标签: go command-line-arguments

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

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])
...

4 个答案:

答案 0 :(得分:21)

os.Argsflag包没有任何了解,并且包含所有命令行参数。试试flag.Args()(当然,在致电flag.Parse()之后)。

答案 1 :(得分:12)

作为后续,解析跟随

之类的命令的标志
runme init -m thisis

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

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

答案 2 :(得分:1)

这也使我感到震惊,并且由于我在应用程序中的多个地方调用了flag.String/flag.Int64/etc,所以我不想在整个地方都经过一个新的flag.FlagSet。 / p>

// 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:])

答案 3 :(得分:0)

您可以检查Arg是否以&#34; - &#34;或&#34; - &#34;并避免在循环中使用该Arg。

例如:

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