• go - flag包(处理命令行参数小能手)


    前言

    在golang中有很多方法来处理命令行参数,简单情况下可以不使用任何库,直接使用os.Args;
    但是golang标准库提供了flag包来专门处理命令行参数
    当然还有第三方提供的处理命令行参数的库cobra、cli可以参考。

    flag包绑定解析参数的三种定义方式

    (1) flag.Xxx() 例如:flag.Int, flag.String, 返回解析变量类型的指针

    package main
    
    import (
        "flag"
        "fmt"
    )
    
    var (
    	host *string
    	port *int
    )
    
    func init()  {
    	host = flag.String("host", "127.0.0.1", "请输入host地址")
    	port = flag.Int("port", 3306, "请输入端口号")
    }
    
    func main() {
        flag.Parse() // 解析参数
        fmt.Printf("%s:%d\n", *host, *port)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    执行:go run main.go
    输出:127.0.0.1:3306
    
    执行: go run main.go -host=192.168.0.1 -port=8080 
    输出:192.168.0.1:8080
    
    执行:go run main.go -host 192.168.0.1
    输出:192.168.0.1:3306
    
    执行:go run main.go -host=192.168.0.1 -port
    输出:invalid value "" for flag -port: parse error
         Usage of xxxxx/exe/main:
            -host string
                 请输入host地址 (default "127.0.0.1")
            -port int
                 请输入端口号 (default 3306)
         exit status 2
    
    执行:go run main.go -h
    输出:Usage of xxxxx/exe/main:
            -host string
                请输入host地址 (default "127.0.0.1")
            -port int
                请输入端口号 (default 3306)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    (2) flag.XxxVar() 例如:flag.IntVar, flag.StringVar 获取解析变量类型的值

    package main
    
    import (
    	"flag"
    	"fmt"
    )
    
    var (
    	host string
    	port int
    )
    
    func init() {
    	flag.StringVar(&host, "host", "127.0.0.1", "请输入host地址")
    	flag.IntVar(&port, "port", 3306, "请输入端口号")
    }
    
    func main() {
    	flag.Parse() // 解析参数
    	fmt.Printf("%s:%d\n", host, port)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    执行效果同上
    
    • 1

    (3)自定义参数解析flag.Var()

    我们可以看下flag.go源码:

    func Var(value Value, name string, usage string) {
        CommandLine.Var(value, name, usage)
    }
    
    type Value interface {
        String() string
        Set(string) error
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    使用flag.Var函数第一个参数我们需要传入一个Value类型的值,Value是一个接口类型,定义了两个方法。
    接下来我们去实现这两个方法:

    package main
    
    import (
    	"flag"
    	"fmt"
    	"strings"
    )
    
    // 自定义类型
    type HandsomeBoys []string
    
    // 实现String()方法
    func (h *HandsomeBoys) String() string {
    	return fmt.Sprintf("%v", *h)
    }
    
    // 实现Set方法,Set接口决定了如何解析flag的值
    func (h *HandsomeBoys) Set(s string) error {
    	for _, v := range strings.Split(s, ",") {
    		*h = append(*h, v)
    	}
    	return nil
    }
    
    // 定义一个HandsomeBoys类型的变量
    var boys HandsomeBoys
    
    func init() {
    	// 绑定变量boys
    	flag.Var(&boys, "boys", "请输入一组帅气的男孩名称:-boys=彭于晏,吴彦祖")
    }
    
    func main() {
    	flag.Parse()
    	fmt.Println(boys)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    输入:go run var/main.go
    输出:[]
    
    输入:go run var/main.go -boys=吴彦波,胡歌
    输出:[吴彦波 胡歌]
    
    • 1
    • 2
    • 3
    • 4
    • 5

    拓展

    1、go的os模块

    使用 os.Args 也能获取命令行参数,但是这个功能有点欠缺。
    例如不能接收像-u root -p 3306这样指定key的值,只能接收像root 3306这样的方式。
    示例:

    package main
    
    import (
    	"fmt"
    	"os"
    )
    
    var cmdArgs []string
    
    func init()  {
    	cmdArgs = os.Args
    }
    
    func main() {
    	for index, value := range cmdArgs {
    		fmt.Printf("索引:%v,value值:%v\n", index, value)
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    输入:go build -o main.exe main.go 
         ./main.exe root 3306 
    输出:索引:0,value值:./main.exe
         索引:1,value值:root
         索引:2,value值:3306
    
    • 1
    • 2
    • 3
    • 4
    • 5

    注:返回的cmdArgs是一个切片,第一个值是自己的文件名。
    如果不想要自己第一个值,直接 cmdArgs = os.Args[1:] 即可。

    2、viper + flag

    有意思的是,可以将viper同flag结合使用。
    示例:

    package main
    
    import (
    	"flag"
    	"fmt"
    	"github.com/spf13/pflag"
    	"github.com/spf13/viper"
    )
    
    func main() {
    	// using standard library "flag" package
    	flag.String("flagname", "root", "help message for flagname")
    
    	pflag.CommandLine.AddGoFlagSet(flag.CommandLine)
    	pflag.Parse()
    	viper.BindPFlags(pflag.CommandLine)
    
    	myFlagname := viper.GetString("flagname") // retrieve value from viper
    	fmt.Println("myFlagname:", myFlagname)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    输入:go run flagUtil.go -h
    输出:Usage of xxxxx/exe/flagUtil:
            --flagname string   help message for flagname (default "root")
         pflag: help requested
    
    输入:go run flagUtil.go
    输出:myFlagname: 1234
    
    输入:go run flagUtil.go --flagname 吴彦波
    输出:myFlagname: 吴彦波
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
  • 相关阅读:
    奇瑞QQ冰淇淋,带你踏遍城市的每一个角落
    创建js对象的几种方式
    网页前端知识汇总(三)——网页前端利用二维码插件qrcode生成在线二维码
    真的,Java并发编程基础入门看这个就够了
    target_link_libraries接口的使用
    深入解析C#中的第三方库NPOI:Excel和Word文件处理的利器
    在MySQL中使用MD5加密【入门体验】
    汽车电子——产品标准规范汇总和梳理(电磁兼容)
    【Hack The Box】Linux练习-- Frolic
    什么是 JVM ?
  • 原文地址:https://blog.csdn.net/qq_35535785/article/details/126244116