Mohit
Mohit

Reputation: 95

How to provide the command line args first and then the flags in golang?

Golang's flag package reads the command line flags and args properly if the input provided is of the form : go run main.go -o filename.txt arg1 arg2

But if I try to provide the input like : go run main.go arg1 arg2 -o filename.txt, everything after main.go is read as arguments.

How to make this style work?

My program:

package main

import (
    "flag"
    "fmt"
)

func main() {

    var output string
    flag.StringVar(&output, "o", "", "Writes output to the file specified")
    flag.Parse()
    fmt.Println("Positional Args : ", flag.Args())
    fmt.Println("Flag -o : ", output)
}

go run main.go -o filename.txt arg1 arg2

Output:

Positional Args :  [arg1 arg2]
Flag -o :  filename.txt

go run main.go arg1 arg2 -o filename.txt

Output:

Positional Args :  [arg1 arg2 -o filename.txt]
Flag -o :

Upvotes: 6

Views: 2762

Answers (1)

Vorsprung
Vorsprung

Reputation: 34327

If you shimmy around with the contents of os.Args, it is possible to accept arg1 arg2 -o filename.txt

Go through the os.Args that is passed in from the command line in the for loop

If a - is seen then set a condition that indicates the first flag has been seen

If the condition is set then populate the "notargs" list. Otherwise, populate the "args" list

There is a bit of extra complication here as the args list that is used to set os.Args to the values that will do the flag processing must include the program name (the original os.Arg[0]) as the first value

This solution does not work with -o filename.txt arg1 arg2

package main

import (
    "flag"
    "fmt"
    "os"
)

func main() {

    var output string
    var args[]string
    var notargs[]string
    var in_flags bool=false
    for i:=0; i<len(os.Args); i++ {
      if os.Args[i][0]=='-' {
       in_flags=true
      }
      if i==0 || in_flags {
        notargs=append(notargs,os.Args[i])
      } else {
        args=append(args,os.Args[i])
      }
    }
    os.Args=notargs
    flag.StringVar(&output, "o", "", "Writes output to the file specified")
    flag.Parse()
    fmt.Println("args ",args)
    fmt.Println("Flag -o : ", output)
}

Upvotes: 3

Related Questions