Go之flag

 

定义flag参数,有三种方式
1. 通过flag.String(), Bool(), Int() 等flag.Xxx()方法,该种方式返回一个相应的指针
var ip = flag.Int("flagname", 1234, "help message for flagname")
2.通过flag.XxxVar()方法将flag绑定到一个变量,该种方式返回值类型
var flagvar int
flag.IntVar(&flagvar, "flagname", 1234, "help message for flagname")
3. 通过flag.Var()绑定自定义类型,自定义类型需要实现Value接口(Receives必须为指针),默认值为该变量类型的初始值
flag.Var(&flagVal, "name", "help message for flagname")

 测试代码

package main
import (
        "flag"
        "os"
        "fmt"
)

func main() {
    fmt.Printf("os.Args[]:%s\n", os.Args);
    fmt.Println("tail: ", flag.Args())

    //定义标志
    //1.name:命令行参数名称,比如 -b, -help
    //2.value:默认值,未显式指定的参数,给出隐式的默认值
    //3.usage:提示信息,如果给出的参数不正确或者需要查看帮助 -help,那么会给出这里指定的字符串
    // 这声明了一个string flag,都存储在指针dir中,类型为 *string。
    dir := flag.String("b", "~/soft", "backup path")
    mode := flag.Bool("d", false, "debug mode")

    //使用 Var() 函数将标志绑定到一个变量。
    var flagInt int
    flag.IntVar(&flagInt, "i", 123, "this is a integer")

    //解析命令行标志,必须在定义了所有标志之后并且在程序访问标志之前调用。
    flag.Parse()

    //NFlag 返回已设置的命令行标志的数量。
    fmt.Println(flag.NFlag())
    //NArg 是标志处理后剩余的参数数量。
    fmt.Println(flag.NArg())

    fmt.Println("dir: ", *dir)
    fmt.Println("mode: ", *mode)
    fmt.Println("flagInt: ", flagInt)
    fmt.Println("tail: ", flag.Args())//剩余未处理的参数
}

结果

cts@cts-pc:~/test/bak$ go run first.go --help
os.Args[]:[/tmp/go-build331859944/b001/exe/first --help]
tail:  []
Usage of /tmp/go-build331859944/b001/exe/first:
  -b string
        backup path (default "~/soft")
  -d    debug mode
  -i int
        this is a integer (default 123)
cts@cts-pc:~/test/bak$
cts@cts-pc:~/test/bak$
cts@cts-pc:~/test/bak$ go run first.go -b ssxx -d=true -i 32  1111 2222
os.Args[]:[/tmp/go-build216792631/b001/exe/first -b ssxx -d=true -i 32 1111 2222]
tail:  []
3
2
dir:  ssxx
mode:  true
flagInt:  32
tail:  [1111 2222]

测试2

package main
import (
        "os"
        "flag"
        "fmt"
)
func main() {
    flagSet := flag.NewFlagSet("main", flag.ExitOnError)
    // 参数定义
    //version = flagSet.Bool("version", false, "print version string")
    flagSet.Bool("version", false, "print version string")

    // 解析
    flagSet.Parse(os.Args[1:])
    // 使用参数 (如果参数没有赋值)
    v := flagSet.Lookup("version").Value.(flag.Getter).Get().(bool)
    fmt.Println(v)
}

cts@cts-pc:~/test$ go run t.go -version=true
true
cts@cts-pc:~/test$ go run t.go --help
Usage of main:
-version
print version string

测试3

package main

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

func main(){
   foostr := flag.NewFlagSet("str",flag.ExitOnError)
   strValue := foostr.String("a","string","打印字符串")
   intValue := foostr.Int("b",1,"打印数值")
  
   if len(os.Args)<1{
      fmt.Println("expected 'str' subcommands")
      os.Exit(1)
   }
   switch os.Args[1]{
   case "str":
      foostr.Parse(os.Args[2:])
      fmt.Println("a", *strValue)
      fmt.Println("b", *intValue)
   default:
      fmt.Println("expected 'str' subcommands")
      os.Exit(1)
   }
}

 

cts@cts-pc:~/test$ go run s.go str
a string
b 1
cts@cts-pc:~/test$ go run s.go str -a sssss -b 123
a sssss
b 123
cts@cts-pc:~/test$ go run s.go --help
expected 'str' subcommands
exit status 1

测试四

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

func main() {
        var value string
        flag.StringVar(&value, "v", "defaultValue", "Usage:xxx")
        flag.Parse()

        fmt.Println("Args1:", flag.Arg(0))
        fmt.Println("Args2:", flag.Arg(1))
        fmt.Println("Args3:", flag.Arg(2))
        fmt.Println("value:", value)
        fmt.Println("os.Args[0]:", os.Args[0])
        fmt.Println("os.Args[1]:", os.Args[1])
        fmt.Println("os.Args[2]:", os.Args[2])
}

 

os.Args[0]: ./test
os.Args[1]: -v
os.Args[2]: sss
cts@cts-pc:~/test$
cts@cts-pc:~/test$
cts@cts-pc:~/test$ ./test 111 222 333 -v sss
Args1: 111
Args2: 222
Args3: 333
value: defaultValue
os.Args[0]: ./test
os.Args[1]: 111
os.Args[2]: 222

-v放在后面,为什么没有被正确解析出来?这是因为解析到非FLag变量就停止解析Flag参数了。所以,flag参数应该放在普通参数的前面指定。 

 

// These examples demonstrate more intricate uses of the flag package.
package main

import (
        "errors"
        "flag"
        "fmt"
        "strings"
        "time"
)

// Example 1: A single string flag called "species" with default value "gopher".
var species = flag.String("species", "gopher", "the species we are studying")

// Example 2: Two flags sharing a variable, so we can have a shorthand.
// The order of initialization is undefined, so make sure both use the
// same default value. They must be set up with an init function.
var gopherType string

func init() {
        const (
                defaultGopher = "pocket"
                usage         = "the variety of gopher"
        )
        flag.StringVar(&gopherType, "gopher_type", defaultGopher, usage)
        flag.StringVar(&gopherType, "g", defaultGopher, usage+" (shorthand)")
}

// Example 3: A user-defined flag type, a slice of durations.
type interval []time.Duration

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (i *interval) String() string {
        return fmt.Sprint(*i)
}

// Set is the method to set the flag value, part of the flag.Value interface.
// Set's argument is a string to be parsed to set the flag.
// It's a comma-separated list, so we split it.
func (i *interval) Set(value string) error {
        // If we wanted to allow the flag to be set multiple times,
        // accumulating values, we would delete this if statement.
        // That would permit usages such as
        //      -deltaT 10s -deltaT 15s
        // and other combinations.
        if len(*i) > 0 {
                return errors.New("interval flag already set")
        }
        for _, dt := range strings.Split(value, ",") {
                duration, err := time.ParseDuration(dt)
                if err != nil {
                        return err
                }
                *i = append(*i, duration)
        }
        return nil
}

// Define a flag to accumulate durations. Because it has a special type,
// we need to use the Var function and therefore create the flag during
// init.

var intervalFlag interval

func init() {
        // Tie the command-line flag to the intervalFlag variable and
        // set a usage message.
        flag.Var(&intervalFlag, "deltaT", "comma-separated list of intervals to use between events")
}

func main() {
        // All the interesting pieces are with the variables declared above, but
        // to enable the flag package to see the flags defined there, one must
        // execute, typically at the start of main (not init!):
        flag.Parse()
        // We don't run it here because this is not a main function and
        // the testing suite has already parsed the flags.
        fmt.Printf("species:%s\n", *species)
        fmt.Printf("gopherType:%s\n", gopherType)
        fmt.Println(intervalFlag)
}

 

cts@cts-pc:~/test/bak$ ./bak --help
Usage of ./bak:
  -deltaT value
        comma-separated list of intervals to use between events
  -g string
        the variety of gopher (shorthand) (default "pocket")
  -gopher_type string
        the variety of gopher (default "pocket")
  -species string
        the species we are studying (default "gopher")
cts@cts-pc:~/test/bak$
cts@cts-pc:~/test/bak$
cts@cts-pc:~/test/bak$ ./bak -g "gggg" -species "ssssss" -deltaT 61m,72h,80s
species:ssssss
gopherType:gggg
[1h1m0s 72h0m0s 1m20s]

 

posted @ 2021-01-30 17:31  牧 天  阅读(257)  评论(0)    收藏  举报