Golang學習筆記--flag包

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

原文連結: http://www.cloudnoter.com/?p=131

flag包是用來處理命令參數的。總得來說,其通過將命令列標誌與某一具體變數進行綁定,開發人員通過使用該變數進行商務邏輯處理。

一、FlagSet是該包的核心類型:
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.    Usage func()    name          string    parsed        bool    actual        map[string]*Flag    // 存放命令列中實際輸入的標誌映射    formal        map[string]*Flag  // 存放該執行個體可以處理的命令列標誌映射    args          []string // arguments after flags 存放非標誌的參數列表(即標誌後面的參數)    exitOnError  bool    // does the program exit if there's an error?    errorHandling ErrorHandling    output        io.Writer // nil means stderr; use out() accessor}
該類型同時提供了一系列的方法集合【MethodSet】,通過該方法集用於可以實現靈活的命令列標誌處理。


二、flag包export的變數:CommandLine
// CommandLine is the default set of command-line flags, parsed from os.Args.// The top-level functions such as BoolVar, Arg, and on are wrappers for the// methods of CommandLine.var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
該包提供了一個預設變數:CommandLine,其為FlatSet的一個變數(用物件導向的術語叫做:FlagSet的一個執行個體)

該flag包export的所有函數本質上都是調用FlagSet類型變數(執行個體):CommandLine的方法實現。如下:
// Int defines an int flag with specified name, default value, and usage string.// The return value is the address of an int variable that stores the value of the flag.func Int(name string, value int, usage string) *int {    return CommandLine.Int(name, value, usage)}


三、flag包支援的標誌格式
Command line flag syntax:        -flag // 代表bool值,相當於-flag=true        -flag=x        -flag x  // non-boolean flags only  不支援bool值標誌    One or two minus signs may be used; they are equivalent.  // -flag=value與--flag=value是等效的    The last form is not permitted for boolean flags because the    meaning of the command        cmd -x *    will change if there is a file called 0, false, etc.  You must    use the -flag=false form to turn off a boolean flag.    Flag parsing stops just before the first non-flag argument    ("-" is a non-flag argument) or after the terminator "--".  // 碰到連續兩個"-"號且參數長度為2時則終止標誌解析


四、標誌綁定相關方法:以綁定int類型為例。
// IntVar defines an int flag with specified name, default value, and usage string.// The argument p points to an int variable in which to store the value of the flag.// FlagSet提供的綁定int類型標誌的方法,無傳回值。通過傳入int類型指標變數進行綁定,當調用該方法後,會將綁定資訊存入FlagSet.formal映射中func (f *FlagSet) IntVar(p *int, name string, value int, usage string) {    f.Var(newIntValue(value, p), name, usage)}//與上述方法相對應的flag包export的函數:// IntVar defines an int flag with specified name, default value, and usage string.// The argument p points to an int variable in which to store the value of the flag.func IntVar(p *int, name string, value int, usage string) {    CommandLine.Var(newIntValue(value, p), name, usage)}//使用樣本var flagvar intflag.IntVar(&flagvar, "flagname2", 1234, "help message for flagname2")// Int defines an int flag with specified name, default value, and usage string.// The return value is the address of an int variable that stores the value of the flag.// FlagSet提供的綁定int類型標誌的方法,有傳回值,返回int類型指標,當調用該方法後,會將綁定資訊存入FlagSet.formal映射中func (f *FlagSet) Int(name string, value int, usage string) *int {    p := new(int)    f.IntVar(p, name, value, usage)    return p}//與上述方法相對應的flag包export的函數:// Int defines an int flag with specified name, default value, and usage string.// The return value is the address of an int variable that stores the value of the flag.func Int(name string, value int, usage string) *int {    return CommandLine.Int(name, value, usage)}//使用樣本var flagvar = flag.Int("flagname", 1234, "help message for flagname")


五、解析標誌的相關關鍵源碼
// Parse parses the command-line flags from os.Args[1:].  Must be called// after all flags are defined and before flags are accessed by the program.// flag包export的函數,調用時機為:在設定好標誌與變數的綁定關係後,調用flag.Parse()。func Parse() {    // Ignore errors; CommandLine is set for ExitOnError.    CommandLine.Parse(os.Args[1:])}// Parse parses flag definitions from the argument list, which should not// include the command name.  Must be called after all flags in the FlagSet// are defined and before flags are accessed by the program.// The return value will be ErrHelp if -help was set but not defined.// FlagSet類型提供的實現方法func (f *FlagSet) Parse(arguments []string) error {    f.parsed = true    f.args = arguments    for {        seen, err := f.parseOne()        if seen {            continue        }        if err == nil {            break        }        switch f.errorHandling {        case ContinueOnError:            return err        case ExitOnError:            os.Exit(2)        case PanicOnError:            panic(err)        }    }    return nil}// parseOne parses one flag. It reports whether a flag was seen.// 解析每個標誌並返回相關結果,若碰到 '-' 或 '--' 時也會直接終止整個標誌解析過程,每解析成功一個標誌就會將該標誌資訊放入FlagSet.actual映射中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    }    num_minuses := 1    if s[1] == '-' {        num_minuses++        if len(s) == 2 { // "--" terminates the flags            f.args = f.args[1:]            return false, nil        }    }    name := s[num_minuses:]    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:]    has_value := false    value := ""    for i := 1; i < len(name); i++ { // equals cannot be first        if name[i] == '=' {            value = name[i+1:]            has_value = 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)    }    if fv, ok := flag.Value.(boolFlag); ok && fv.IsBoolFlag() { // special case: doesn't need an arg        if has_value {            if err := fv.Set(value); err != nil {                return false, f.failf("invalid boolean value %q for  -%s: %v", value, name, err)            }        } else {            fv.Set("true")        }    } else {        // It must have a value, which might be the next argument.        if !has_value && len(f.args) > 0 {            // value is the next arg            has_value = true            value, f.args = f.args[0], f.args[1:]        }        if !has_value {            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}


聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.