go語言解析命令列引數的實現
一、實現程式碼如下
// fffggg project main.go package main
import ( "flag" "fmt" )
func main() {
var num int var mode string var encrypt bool
// 具體用法如下:
// command -flagname // command --flagname // command -flagname= // command --flagname= // 注意“=”號前面和後面不能有空格
// 第一步,定義Flag引數 flag.IntVar(&num, "num", 38, "--num the password length") flag.StringVar(&mode, "mode", "mix", "--mode the password generate mode") flag.BoolVar(&encrypt, "encrypt", true, "--encrypt the password use RSA")
// 第二步,呼叫flag.Parse()解析命令列引數到定義的Flag flag.Parse()
// 呼叫Parse解析後,就可以直接使用繫結的變量了 fmt.Printf("num:%d mode:%s encrypt:%v\n", num, mode, encrypt) }
二、編譯後測試結果
./fffggg --num 3 --mode nnn --encrypt true num:3 mode:nnn encrypt:true
./fffggg --num 3 --mode nnn --encrypt false
num:3 mode:nnn encrypt:true
三、出現錯誤解決方法
將go/src/flag/flag.go中下面程式碼的紅色部分程式碼提前即可
// parseOne parses one flag. It reports whether a flag was seen. func (f *FlagSet) parseOne() (bool, error) { if len(f.args) == 0 { return false, nil } s := f.args[0] if len(s) == 0 || s[0] != '-' || len(s) == 1 { return false, nil } numMinuses := 1 if s[1] == '-' { numMinuses++ if len(s) == 2 { // "--" terminates the flags f.args = f.args[1:] return false, nil } } name := s[numMinuses:] if len(name) == 0 || name[0] == '-' || name[0] == '=' { return false, f.failf("bad flag syntax: %s", s) }
// it's a flag. does it have an argument? f.args = f.args[1:] hasValue := false value := "" for i := 1; i < len(name); i++ { // equals cannot be first if name[i] == '=' { value = name[i+1:] hasValue = true name = name[0:i] break } } m := f.formal flag, alreadythere := m[name] // BUG if !alreadythere { if name == "help" || name == "h" { // special case for nice help message. f.usage() return false, ErrHelp } return false, f.failf("flag provided but not defined: -%s", name) }
// It must have a value, which might be the next argument. if !hasValue && len(f.args) > 0 { // value is the next arg hasValue = true value, f.args = f.args[0], f.args[1:] }
if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
if hasValue {
if err := fv.Set(value); err != nil {
return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
}
} else {
if err := fv.Set("true"); err != nil {
return false, f.failf("invalid boolean flag %s: %v", name, err)
}
}
} else { // It must have a value, which might be the next argument.
if !hasValue && len(f.args) > 0 {
// value is the next arg
hasValue = true
value, f.args = f.args[0], f.args[1:]
}
if !hasValue {
return false, f.failf("flag needs an argument: -%s", name)
}
if err := flag.Value.Set(value); err != nil {
return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
}
}
if f.actual == nil {
f.actual = make(map[string]*Flag)
}
f.actual[name] = flag
return true, nil
}