go run main.go go -name 诶嘿 # name: 诶嘿 go run main2.go php -n 诶嘿啊 # name: 诶嘿啊 go run main2.go php -name 诶嘿啊 # flag provided but not defined: -name # Usage of php: # -n string # 输出参数n (default "php语言") # exit status 2
... // 接上面代码 // it's a flag. does it have an argument? f.args = f.args[1:] // 注意此时f.args已经去掉了第一个参数 hasValue := false value := "" for i := 1; i < len(name); i++ { // equals cannot be first if name[i] == '=' { // name是上一部分代码中,已经将'-'去掉的命令行参数 value = name[i+1:] hasValue = true name = name[0:i] break } } ...
这一部分主要是处理命令行参数带=的情况,比如--name=rzzy,需要将参数名和参数值分开
1 2 3 4 5 6 7 8 9
m := f.formal // f.formal 为 map[string]*Flag,保存已经定义过的flag与对应的名字 flag, alreadythere := m[name] // BUG if !alreadythere { if name == "help" || name == "h" { // special case for nice help message. f.usage() returnfalse, ErrHelp } returnfalse, f.failf("flag provided but not defined: -%s", name) }
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 { returnfalse, f.failf("invalid boolean value %q for -%s: %v", value, name, err) } } else { if err := fv.Set("true"); err != nil { returnfalse, 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 { returnfalse, f.failf("flag needs an argument: -%s", name) } if err := flag.Value.Set(value); err != nil { returnfalse, f.failf("invalid value %q for flag -%s: %v", value, name, err) } }
这一部分是判断该命令行参数定义是否为布尔型,通过该 flag 所提供的 Value.Set 方法将参数值设置到对应的 flag 中去
非布尔型的,也同样将其flag 所提供的 Value.Set 方法将参数值设置到对应的 flag 中去
1 2 3 4 5
if f.actual == nil { // f.actual 为 map[string]*Flag,保存本次解析时用到的命令行参数名与flag对象 f.actual = make(map[string]*Flag) } f.actual[name] = flag returntrue, nil