Cobrautils: 让绑定参数更简单
建议点击 查看原文 查看最新内容。
原文链接:
https://typonotes.com/posts/2024/03/29/cobrautils-bind-parameters/
有群友说, python 命令行绑定参数方便。 本来没什么
还要顺口踩一脚 go 的参数绑定不方便。 这个能忍?
CobraUtils 使用结构体绑定参数
cobra
绝对是命令行库中的第一梯队, kubectl 也是使用这个库实现的。
现在的问题是: 怎么才能 快速方便 的绑定参数呢?
那就必须用 反射 实现了呗。 于是便有了 cobrautils
https://github.com/go-jarvis/cobrautils
用了之后, 绑定参数的过程 就像 解析 JSON 一样简单
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| // 参数列表
type student struct {
Name string `flag:"name" usage:"student name" persistent:"true"`
Age int64 `flag:"age" usage:"student age" shorthand:"a"`
}
// 默认值
stu := student{
Name: "zhangsanfeng",
Age: 20100
}
// 编译结果
go run . --name wenzhaolun
Usage:
root [flags]
Flags:
-a, --age int student age (default 20100)
-h, --help help for root
--name string student name (default "zhangsanfeng")
|
更多请看完整 Demo
1. 安装
1
| go get -u github.com/go-jarvis/cobrautils
|
2. 使用方式
Attention: 由于 cobra 中对数据的处理方法很细致, 因此数据目前支持
- 字符串:
- 数字:
int, int64, uint, uint64
。*int, *int8, *int16, *int32, *int64
*uint, *uint8, *uint16, *uint32, *uint64
- 布尔类型:
- 切片:
- 时间:
timeDuration, *time.Duration
flag 与 cobra
定义一致
1
2
3
| func (f *FlagSet) Uint64VarP(p *uint64, name, shorthand string, value uint64, usage string) {
f.VarP(newUint64Value(value, p), name, shorthand, usage)
}
|
3. flag 设置
1
2
3
4
5
6
7
| type student struct {
Name string `flag:"name" usage:"student name" persistent:"true"`
Age int64 `flag:"age" usage:"student age" shorthand:"a"`
NamePtr *string `flag:"nameptr" usage:"student name" persistent:"true"`
AgePtr *int64 `flag:"ageptr" usage:"student age" shorthand:"a"`
}
|
flag:"config"
: flag 的名字, --config
, 嵌套 struct 之间使用 .
连接, --config.password
shorthand:"c"
: 参数简写 -c
, 简写没有潜逃usage:"comment balalal"
: 参数说明persistent
: 全局
4. flag 设置指针
从 v1.3.0 开始, flag 支持有限指针集, 以解决常用类型的 0 值问题。
包括 *string, *int, *int64, *bool
https://runsisi.com/2019/04/29/go-pointer-flag/
5. 默认值设置
由于所有参数的值最终都需要一个接收者, 保存之后才能够背调用。
因此, 默认值的设置就放在 struct
实例化一个对象中。
1
2
3
4
| stu := student{
Name: "zhangsanfeng",
Age: 20100
}
|
6. 键值绑定
1
2
3
4
5
6
| // 绑定
cobrautils.BindFlags(rootCmd, &stu)
_ = rootCmd.Execute()
// 打印结果
fmt.Printf("%+v", stu)
|
7. 完整 Demo
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
| package main
import (
"fmt"
"github.com/go-jarvis/cobrautils"
"github.com/spf13/cobra"
)
type student struct {
Name string `flag:"name" usage:"student name" persistent:"true"`
Age int64 `flag:"age" usage:"student age" shorthand:"a"`
}
var rootCmd = &cobra.Command{
Use: "root",
Run: func(cmd *cobra.Command, args []string) {
_ = cmd.Help()
},
}
func main() {
stu := student{
Name: "zhangsanfeng",
Age: 20100
}
cobrautils.BindFlags(rootCmd, &stu)
_ = rootCmd.Execute()
fmt.Printf("%+v", stu)
}
|
执行结果
1
2
3
4
5
6
7
8
9
| go run . --name wenzhaolun
Usage:
root [flags]
Flags:
-a, --age int student age (default 20100)
-h, --help help for root
--name string student name (default "zhangsanfeng")
{Name:wenzhaolun Age:20100}
|
技术要点: QA
kind
and type
相较于 Type 而言,Kind 所表示的范畴更大。 类似于家用电器(Kind)和电视机(Type)之间的对应关系。或者电视机(Kind)和 42 寸彩色电视机(Type)
Type 是类型。Kind 是类别。Type 和 Kind 可能相同,也可能不同。
通常基础数据类型的 Type 和 Kind 相同
自定义数据类型则不同。
对于反射中的 kind 我们既可以通过 reflect.Type 来获取,也可以通过 reflect.Value 来获取。他们得到的值和类型均是相同的。