flag.go
别看内容挺多一千多行,核心也就只有 FlagSet 的 parseOne 方法
// src/flag/flag.go ---- line 315// A FlagSet represents a set of defined flags. The zero value of a FlagSet// has no name and has ContinueOnError error handling.//// Flag names must be unique within a FlagSet. An attempt to define a flag whose// name is already in use will cause a panic.type FlagSet struct {// Usage is the function called when an error occurs while parsing flags.// The field is a function (not a method) that may be changed to point to// a custom error handler. What happens after Usage is called depends// on the ErrorHandling setting; for the command line, this defaults// to ExitOnError, which exits the program after calling Usage.Usage func()name stringparsed boolactual map[string]*Flagformal map[string]*Flagargs []string // arguments after flagserrorHandling ErrorHandlingoutput io.Writer // nil means stderr; use out() accessor}// A Flag represents the state of a flag.type Flag struct {Name string // name as it appears on command lineUsage string // help messageValue Value // value as setDefValue string // default value (as text); for usage message}// src/flag/flag.go ---- line 888// 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) < 2 || s[0] != '-' {return false, nil}numMinuses := 1if s[1] == '-' {numMinuses++if len(s) == 2 { // "--" terminates the flagsf.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 := falsevalue := ""for i := 1; i < len(name); i++ { // equals cannot be firstif name[i] == '=' {value = name[i+1:]hasValue = truename = name[0:i]break}}m := f.formalflag, alreadythere := m[name] // BUGif !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)}if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an argif 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 arghasValue = truevalue, 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] = flagreturn true, nil}
当然说是核心,其实也就只是长了一点,没有什么花式的技巧,从头看到尾就知道干啥了。
