flag.go

别看内容挺多一千多行,核心也就只有 FlagSetparseOne 方法

  1. // src/flag/flag.go ---- line 315
  2. // A FlagSet represents a set of defined flags. The zero value of a FlagSet
  3. // has no name and has ContinueOnError error handling.
  4. //
  5. // Flag names must be unique within a FlagSet. An attempt to define a flag whose
  6. // name is already in use will cause a panic.
  7. type FlagSet struct {
  8. // Usage is the function called when an error occurs while parsing flags.
  9. // The field is a function (not a method) that may be changed to point to
  10. // a custom error handler. What happens after Usage is called depends
  11. // on the ErrorHandling setting; for the command line, this defaults
  12. // to ExitOnError, which exits the program after calling Usage.
  13. Usage func()
  14. name string
  15. parsed bool
  16. actual map[string]*Flag
  17. formal map[string]*Flag
  18. args []string // arguments after flags
  19. errorHandling ErrorHandling
  20. output io.Writer // nil means stderr; use out() accessor
  21. }
  22. // A Flag represents the state of a flag.
  23. type Flag struct {
  24. Name string // name as it appears on command line
  25. Usage string // help message
  26. Value Value // value as set
  27. DefValue string // default value (as text); for usage message
  28. }
  29. // src/flag/flag.go ---- line 888
  30. // parseOne parses one flag. It reports whether a flag was seen.
  31. func (f *FlagSet) parseOne() (bool, error) {
  32. if len(f.args) == 0 {
  33. return false, nil
  34. }
  35. s := f.args[0]
  36. if len(s) < 2 || s[0] != '-' {
  37. return false, nil
  38. }
  39. numMinuses := 1
  40. if s[1] == '-' {
  41. numMinuses++
  42. if len(s) == 2 { // "--" terminates the flags
  43. f.args = f.args[1:]
  44. return false, nil
  45. }
  46. }
  47. name := s[numMinuses:]
  48. if len(name) == 0 || name[0] == '-' || name[0] == '=' {
  49. return false, f.failf("bad flag syntax: %s", s)
  50. }
  51. // it's a flag. does it have an argument?
  52. f.args = f.args[1:]
  53. hasValue := false
  54. value := ""
  55. for i := 1; i < len(name); i++ { // equals cannot be first
  56. if name[i] == '=' {
  57. value = name[i+1:]
  58. hasValue = true
  59. name = name[0:i]
  60. break
  61. }
  62. }
  63. m := f.formal
  64. flag, alreadythere := m[name] // BUG
  65. if !alreadythere {
  66. if name == "help" || name == "h" { // special case for nice help message.
  67. f.usage()
  68. return false, ErrHelp
  69. }
  70. return false, f.failf("flag provided but not defined: -%s", name)
  71. }
  72. if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg
  73. if hasValue {
  74. if err := fv.Set(value); err != nil {
  75. return false, f.failf("invalid boolean value %q for -%s: %v", value, name, err)
  76. }
  77. } else {
  78. if err := fv.Set("true"); err != nil {
  79. return false, f.failf("invalid boolean flag %s: %v", name, err)
  80. }
  81. }
  82. } else {
  83. // It must have a value, which might be the next argument.
  84. if !hasValue && len(f.args) > 0 {
  85. // value is the next arg
  86. hasValue = true
  87. value, f.args = f.args[0], f.args[1:]
  88. }
  89. if !hasValue {
  90. return false, f.failf("flag needs an argument: -%s", name)
  91. }
  92. if err := flag.Value.Set(value); err != nil {
  93. return false, f.failf("invalid value %q for flag -%s: %v", value, name, err)
  94. }
  95. }
  96. if f.actual == nil {
  97. f.actual = make(map[string]*Flag)
  98. }
  99. f.actual[name] = flag
  100. return true, nil
  101. }

当然说是核心,其实也就只是长了一点,没有什么花式的技巧,从头看到尾就知道干啥了。