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)
}
执行: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)
(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)
}
执行效果同上
(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
}

使用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)
}
输入:go run var/main.go
输出:[]

输入:go run var/main.go -boys=吴彦波,胡歌
输出:[吴彦波 胡歌]

拓展

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)
	}
}
输入:go build -o main.exe main.go 
     ./main.exe root 3306 
输出:索引:0,value值:./main.exe
     索引:1,value值:root
     索引:2,value值:3306

注:返回的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)
}
输入: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: 吴彦波
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个简单的 Python 程序,用于计算两个数字的和,并通过 GUI 窗口化显示结果。 ```python import tkinter as tk root = tk.Tk() root.title("计算小能手") num1_label = tk.Label(root, text="第一个数字:") num1_label.grid(row=0, column=0) num1_entry = tk.Entry(root) num1_entry.grid(row=0, column=1) num2_label = tk.Label(root, text="第二个数字:") num2_label.grid(row=1, column=0) num2_entry = tk.Entry(root) num2_entry.grid(row=1, column=1) result_label = tk.Label(root, text="") result_label.grid(row=2, column=0, columnspan=2) def calculate(): try: num1 = float(num1_entry.get()) num2 = float(num2_entry.get()) result = num1 + num2 result_label.config(text="结果:%.2f" % result) except ValueError: result_label.config(text="请输入数字!") calculate_button = tk.Button(root, text="计算", command=calculate) calculate_button.grid(row=3, column=0, columnspan=2) root.mainloop() ``` 该程序使用了 tkinter 模块,它是 Python 的标准 GUI 库。在程序中,我们创建了一个窗口并设置了标题。然后,我们创建了三个标签和两个输入框,用于输入两个数字。我们还创建了一个标签,用于显示计算结果。 我们还创建了一个函数 calculate(),用于计算两个数字的和并更新结果标签的文本。该函数首先尝试从输入框中获取两个数字,并将它们相加。如果输入的内容不是数字,它会抛出 ValueError 异常。在这种情况下,我们更新结果标签的文本,以提示用户输入数字。 最后,我们创建了一个“计算”按钮,当用户点击它时,程序将调用 calculate() 函数计算结果并更新结果标签的文本。我们将按钮放置在最后一行,并将其跨越两列。最后,我们调用 mainloop() 函数,使程序进入事件循环,并等待用户与窗口交互。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值