zoukankan      html  css  js  c++  java
  • GO学习笔记

    本文主题:基于os.Args与flag实现Golang命令行解析。

    小慢哥的原创文章,欢迎转载


    目录

    ▪ 一. os.Args
    ▪ 二. flag
    ▪ 三. 结合os.Args与flag实现子命令
    ▪ 附. 参考文档


    一. os.Args

    os.Args用于获取通过命令行传入的参数

    os.Args[0]:程序执行路径
    os.Args[1]:第1个参数
    os.Args[2]:第2个参数
    len(os.Args):参数数量

    示例如下

    package main
    
    import (
        "fmt"
        "os"
    )
    
    func main() {
        fmt.Println("Program:", os.Args[0])
        for i, v := range os.Args[1:] {
            fmt.Printf("Arg[%d]: %v
    ", i, v)
        }
    }
    

    测试效果

    # 编译执行
    go build arg.go
    ./arg foo "hello world" bar
    
    # 输出
    Program: ./arg
    Arg[0]: foo
    Arg[1]: hello world
    Arg[2]: bar
    

    二. flag

    golang内置的flag模块可以实现命令行flag解析。

    什么是flag,举例说明(加粗部分就是flag):

    ▷ wc -l
    ▷ ./configure --prefix=/usr/local/nginx

    示例如下(摘取自gobyexample)

    package main
    
    import (
        "flag"
        "fmt"
    )
    
    func main() {
        // flag.String返回的是指针
        // word表示参数名,foo表示默认值,a string表示参数释义(在-h或解析异常时候会看到)
        // flag.Int、flag.Bool与flag.String同理,不再赘述
        wordPtr := flag.String("word", "foo", "a string")
        numbPtr := flag.Int("numb", 42, "an int")
        boolPtr := flag.Bool("fork", false, "a bool")
    
        // flag.StringVar返回的是非指针
        var svar string
        flag.StringVar(&svar, "svar", "bar", "a string var")
    
        // 进行flag解析
        flag.Parse()
    
        fmt.Println("word:", *wordPtr)
        fmt.Println("numb:", *numbPtr)
        fmt.Println("fork:", *boolPtr)
        fmt.Println("svar:", svar)
        fmt.Println("tail:", flag.Args())
    }
    

    测试效果

    # 编译
    go build flag.go
    
    ./flag -word=opt -numb=7 -fork -svar=flag
    # 输出
    word: opt
    numb: 7
    fork: true
    svar: flag
    tail: []
    
    ./flag -word=opt
    # 输出
    word: opt
    numb: 42
    fork: false
    svar: bar
    tail: []
    
    ./flag -word=opt a1 a2 a3
    # 输出
    word: opt
    numb: 42
    fork: false
    svar: bar
    tail: [a1 a2 a3]
    
    ./flag -word=opt a1 a2 a3 -numb=7
    # 输出
    word: opt
    numb: 42
    fork: false
    svar: bar
    tail: [a1 a2 a3 -numb=7]
    
    ./flag -h
    # 输出
    Usage of ./flag:
      -fork
            a bool
      -numb int
            an int (default 42)
      -svar string
            a string var (default "bar")
      -word string
            a string (default "foo")
    
    ./flag -wat
    # 输出
    flag provided but not defined: -wat
    Usage of ./flag:
    ...
    

    该例子,在测试时候只使用了“单横线+参数名”,实际有4种方式,效果是相同的

    -word opt
    -word=opt
    --word opt
    --word=opt
    

    三. 结合os.Args与flag实现子命令

    如果想实现子命令效果,例如:

    ▷ docker ps --last 10
    ▷ docker images --help

    这需要将os.Args和flag结合使用。基本原理:创建多个flag集合(即*flag.FlagSet),每个flag集合对应不同的os.Args

    示例如下(摘取自gobyexample)

    package main
    
    import (
        "flag"
        "fmt"
        "os"
    )
    
    func main() {
        fooCmd := flag.NewFlagSet("foo", flag.ExitOnError)
        fooEnable := fooCmd.Bool("enable", false, "enable")
        fooName := fooCmd.String("name", "", "name")
    
        barCmd := flag.NewFlagSet("bar", flag.ExitOnError)
        barLevel := barCmd.Int("level", 0, "level")
    
        if len(os.Args) < 2 {
            fmt.Println("expected 'foo' or 'bar' subcommands")
            os.Exit(1)
        }
    
        switch os.Args[1] {
        case "foo":
            fooCmd.Parse(os.Args[2:])
            fmt.Println("subcommand 'foo'")
            fmt.Println(" enable:", *fooEnable)
            fmt.Println(" name:", *fooName)
            fmt.Println(" tail:", fooCmd.Args())
        case "bar":
            barCmd.Parse(os.Args[2:])
            fmt.Println("subcommand 'bar'")
            fmt.Println(" level:", *barLevel)
            fmt.Println(" tail:", barCmd.Args())
        default:
            fmt.Println("expected 'foo' or 'bar' subcommands")
            os.Exit(1)
        }
    }
    

    测试效果

    # 编译
    go build subflag.go
    
    ./subflag foo -enable -name=joe a1 a2
    # 输出
    subcommand 'foo'
      enable: true
      name: joe
      tail: [a1 a2]
    
    ./subflag bar -level 8 a1
    # 输出
    subcommand 'bar'
      level: 8
      tail: [a1]
    
    ./subflag bar -enable a1
    # 输出
    flag provided but not defined: -enable
    Usage of bar:
      -level int
            level
    

    附. 参考文档

    # os.Args
    https://gobyexample.com/command-line-arguments
    
    # flag
    https://gobyexample.com/command-line-flags
    
    # 子命令
    https://gobyexample.com/command-line-subcommands
    
  • 相关阅读:
    NSCharacterSet 最经常使用的使用方法
    IOS
    hdu 3117 Fibonacci Numbers
    Hibernate5配置与使用具体解释
    SDNU 1206.蚂蚁感冒 【代码如此简单,思维练习】【7月29】
    2048游戏分析、讨论与扩展
    hash_set和hash_map
    实现邮箱找回的思路分析
    学习OpenCV——粒子滤波(网上两篇文章总结)
    学习OpenCV——配置CUDA环境
  • 原文地址:https://www.cnblogs.com/fzxiaomange/p/golang-command-parse.html
Copyright © 2011-2022 走看看