golang命令行选项解析插件库go-flags的使用
golang命令行选项解析插件库go-flags的使用
go-flags是一个用于解析命令行参数的Go语言库,它提供了比Go内置flag库更丰富的功能和更好的格式化支持。
主要特性
- 支持短选项(-v)和长选项(–verbose)
- 支持带参数和不带参数的选项
- 支持可选参数和默认值
- 支持多个选项组
- 生成格式良好的帮助信息
- 支持–后的剩余参数
- 支持忽略未知选项
- 支持多种参数指定方式(-I/usr/include, -I=/usr/include, -I /usr/include)
- 支持组合短选项(-aux)
- 支持所有Go基本类型
- 支持多次指定同一选项(可存储为切片或只取最后一次)
- 支持map类型
- 支持回调函数
- 支持命名空间(嵌套选项组)
使用示例
package main
import (
"fmt"
"os/exec"
"strings"
"github.com/jessevdk/go-flags"
)
// 定义选项结构体
type Options struct {
// 布尔切片,每次遇到选项会追加true(可多次设置,如-vvv)
Verbose []bool `short:"v" long:"verbose" description:"显示详细调试信息"`
// 自动转换为uint类型
Offset uint `long:"offset" description:"偏移量"`
// 回调函数,每次找到选项时调用
Call func(string) `short:"c" description:"拨打电话号码"`
// 必填标志
Name string `short:"n" long:"name" description:"名称" required:"true"`
// 限制为预定义字符串集合的标志
Animal string `long:"animal" choice:"cat" choice:"dog"`
// 带值名称的选项
File string `short:"f" long:"file" description:"文件" value-name:"FILE"`
// 指针示例
Ptr *int `short:"p" description:"整数指针"`
// 字符串切片
StringSlice []string `short:"s" description:"字符串切片"`
// 指针切片
PtrSlice []*string `long:"ptrslice" description:"字符串指针切片"`
// map示例
IntMap map[string]int `long:"intmap" description:"字符串到整数的映射"`
// 环境变量示例
Thresholds []int `long:"thresholds" default:"1" default:"2" env:"THRESHOLD_VALUES" env-delim:","`
}
func main() {
var opts Options
// 设置回调函数
opts.Call = func(num string) {
cmd := exec.Command("open", "callto:"+num)
cmd.Start()
cmd.Process.Release()
}
// 解析命令行参数
_, err := flags.Parse(&opts)
if err != nil {
panic(err)
}
// 打印解析结果
fmt.Printf("详细模式: %v\n", opts.Verbose)
fmt.Printf("偏移量: %d\n", opts.Offset)
fmt.Printf("名称: %s\n", opts.Name)
if opts.Animal != "" {
fmt.Printf("动物: %s\n", opts.Animal)
}
if opts.Ptr != nil {
fmt.Printf("指针: %d\n", *opts.Ptr)
}
fmt.Printf("字符串切片: %v\n", opts.StringSlice)
if len(opts.PtrSlice) > 0 {
fmt.Printf("指针切片: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
}
if len(opts.IntMap) > 0 {
fmt.Printf("整数映射: %v\n", opts.IntMap)
}
}
更复杂的示例
package main
import (
"fmt"
"os/exec"
"strings"
"github.com/jessevdk/go-flags"
)
func main() {
var opts struct {
Verbose []bool `short:"v" long:"verbose" description:"显示详细调试信息"`
Offset uint `long:"offset" description:"偏移量"`
Call func(string) `short:"c" description:"拨打电话号码"`
Name string `short:"n" long:"name" description:"名称" required:"true"`
Animal string `long:"animal" choice:"cat" choice:"dog"`
File string `short:"f" long:"file" description:"文件" value-name:"FILE"`
Ptr *int `short:"p" description:"整数指针"`
StringSlice []string `short:"s" description:"字符串切片"`
PtrSlice []*string `long:"ptrslice" description:"字符串指针切片"`
IntMap map[string]int `long:"intmap" description:"字符串到整数的映射"`
}
opts.Call = func(num string) {
cmd := exec.Command("open", "callto:"+num)
cmd.Start()
cmd.Process.Release()
}
// 模拟命令行参数
args := []string{
"-vv",
"--offset=5",
"-n", "Me",
"--animal", "dog",
"-p", "3",
"-s", "hello",
"-s", "world",
"--ptrslice", "hello",
"--ptrslice", "world",
"--intmap", "a:1",
"--intmap", "b:5",
"arg1",
"arg2",
"arg3",
}
// 解析参数
args, err := flags.ParseArgs(&opts, args)
if err != nil {
panic(err)
}
fmt.Printf("详细模式: %v\n", opts.Verbose)
fmt.Printf("偏移量: %d\n", opts.Offset)
fmt.Printf("名称: %s\n", opts.Name)
fmt.Printf("动物: %s\n", opts.Animal)
fmt.Printf("指针: %d\n", *opts.Ptr)
fmt.Printf("字符串切片: %v\n", opts.StringSlice)
fmt.Printf("指针切片: [%v %v]\n", *opts.PtrSlice[0], *opts.PtrSlice[1])
fmt.Printf("整数映射: [a:%v b:%v]\n", opts.IntMap["a"], opts.IntMap["b"])
fmt.Printf("剩余参数: %s\n", strings.Join(args, " "))
}
这个库通过结构体、反射和结构体字段标签来指定命令行选项,使得应用程序选项的指定变得非常简单和简洁。
更多关于golang命令行选项解析插件库go-flags的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang命令行选项解析插件库go-flags的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
go-flags 命令行选项解析库使用指南
go-flags 是一个功能强大的 Go 语言命令行选项解析库,它支持 POSIX/GNU 风格的命令行选项解析。下面我将详细介绍它的使用方法。
基本用法
首先安装 go-flags:
go get github.com/jessevdk/go-flags
1. 定义选项结构
package main
import (
"fmt"
"github.com/jessevdk/go-flags"
"os"
)
type Options struct {
Verbose []bool `short:"v" long:"verbose" description:"Show verbose debug information"`
Port int `short:"p" long:"port" description:"Port to listen on" default:"8080"`
Config string `short:"c" long:"config" description:"Config file path" required:"true"`
}
func main() {
var opts Options
parser := flags.NewParser(&opts, flags.Default)
_, err := parser.Parse()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Options: %+v\n", opts)
}
2. 运行示例
$ go run main.go -c config.yaml -p 9090 -vvv
Options: {Verbose:[true true true] Port:9090 Config:config.yaml}
高级特性
1. 子命令支持
type GlobalOptions struct {
Verbose bool `short:"v" long:"verbose" description:"Show verbose debug information"`
}
type StartCommand struct {
Port int `short:"p" long:"port" description:"Port to listen on" default:"8080"`
}
type StopCommand struct {
Force bool `short:"f" long:"force" description:"Force stop"`
}
func main() {
var globalOpts GlobalOptions
var startCmd StartCommand
var stopCmd StopCommand
parser := flags.NewParser(&globalOpts, flags.Default)
parser.AddCommand("start", "Start the server", "", &startCmd)
parser.AddCommand("stop", "Stop the server", "", &stopCmd)
_, err := parser.Parse()
if err != nil {
os.Exit(1)
}
if parser.Active != nil {
switch parser.Active.Name {
case "start":
fmt.Printf("Starting server on port %d (verbose: %v)\n",
startCmd.Port, globalOpts.Verbose)
case "stop":
fmt.Printf("Stopping server (force: %v, verbose: %v)\n",
stopCmd.Force, globalOpts.Verbose)
}
}
}
2. 自定义验证
type Options struct {
Age int `short:"a" long:"age" description:"Your age" validate:"min=18,max=120"`
}
func main() {
var opts Options
parser := flags.NewParser(&opts, flags.Default)
_, err := parser.Parse()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Age: %d\n", opts.Age)
}
3. 环境变量支持
type Options struct {
Debug bool `long:"debug" env:"APP_DEBUG" description:"Enable debug mode"`
}
func main() {
var opts Options
parser := flags.NewParser(&opts, flags.Default)
_, err := parser.Parse()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Debug mode: %v\n", opts.Debug)
}
4. 自定义处理函数
type Options struct {
Files []string `short:"f" long:"file" description:"Files to process"`
}
func main() {
var opts Options
parser := flags.NewParser(&opts, flags.Default)
parser.AddOption(&flags.Option{
LongName: "custom",
Description: "Custom option",
Required: false,
Handler: func(option *flags.Option) error {
fmt.Println("Custom option handler called")
return nil
},
})
_, err := parser.Parse()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Printf("Files: %v\n", opts.Files)
}
错误处理
go-flags 提供了多种错误处理方式:
func main() {
var opts struct {
Name string `short:"n" long:"name" required:"true"`
}
parser := flags.NewParser(&opts, flags.Default)
_, err := parser.Parse()
if flagsErr, ok := err.(*flags.Error); ok {
switch flagsErr.Type {
case flags.ErrHelp:
// 用户请求帮助信息
os.Exit(0)
case flags.ErrRequired:
fmt.Println("Required option missing:", flagsErr.Message)
default:
fmt.Println("Error:", flagsErr.Message)
}
os.Exit(1)
} else if err != nil {
fmt.Println("Unexpected error:", err)
os.Exit(1)
}
fmt.Println("Name:", opts.Name)
}
总结
go-flags 是一个功能全面的命令行解析库,主要特点包括:
- 支持短选项(-v)和长选项(–verbose)
- 支持子命令
- 支持默认值和必填选项
- 支持环境变量
- 支持自定义验证
- 提供详细的帮助信息生成
- 支持选项分组
通过结构体标签可以方便地定义选项的各种属性,使得代码既简洁又易于维护。