Golang Flag интерпретируется как первый аргумент os.Args - программирование
Подтвердить что ты не робот

Golang Flag интерпретируется как первый аргумент os.Args

Я хотел бы запустить мою программу следующим образом:

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

Я уверен, что это должно быть возможно, но я не могу понять, как это сделать.

EDIT: Спасибо justinas за подсказку с флагом .Args(). Теперь я адаптировал его так:

...
flag.Parse()

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

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

Ответ 1

os.Args ничего не знает о пакете 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

Вы можете проверить, начинается ли Arg с "-" или "-" и не позволяет использовать этот Arg в цикле.

Например:

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