golang基于结构体生成多类型命令行标志的插件库sflags的使用

Golang基于结构体生成多类型命令行标志的插件库sflags的使用

sflags是一个使用结构体、反射和结构体字段标签来定义命令行选项的Golang库。它支持多种类型和特性。

基本使用示例

下面是一个使用sflags的基本示例:

package main

import (
	"flag"
	"log"
	"time"

	"github.com/urfave/sflags/gen/gflag"
)

// HTTP配置结构体
type httpConfig struct {
	Host    string        `desc:"HTTP host"`  // 描述信息
	Port    int           // 端口号
	SSL     bool          // 是否启用SSL
	Timeout time.Duration // 超时时间
}

// 主配置结构体
type config struct {
	HTTP httpConfig // HTTP配置
}

func main() {
	// 初始化配置默认值
	cfg := &config{
		HTTP: httpConfig{
			Host:    "127.0.0.1",
			Port:    6000,
			SSL:     false,
			Timeout: 15 * time.Second,
		},
	}
	
	// 将结构体转换为命令行标志
	err := gflag.ParseToDef(cfg)
	if err != nil {
		log.Fatalf("err: %v", err)
	}
	
	// 解析命令行参数
	flag.Parse()
}

运行上面的代码会生成以下输出:

$ go run ./main.go --help
Usage of _obj/exe/main:
  -http-host value
    	HTTP host (default 127.0.0.1)
  -http-port value
    	 (default 6000)
  -http-ssl
  -http-timeout value
    	 (default 15s)
exit status 2

支持的标志库和特性

sflags支持多种流行的命令行标志库:

隐藏 废弃 短名 环境变量 必填
flag - - - - -
kingpin -
spf13/pflag - -
spf13/cobra - -
urfave/cli -

主要特性

  • 设置环境变量名
  • 设置使用说明
  • 支持长格式和短格式标志
  • 跳过字段
  • 必填字段
  • 废弃和隐藏选项
  • 多个环境变量名
  • 用户自定义类型接口
  • 验证功能(使用govalidator包)
  • 匿名嵌套结构支持

支持的结构体类型

  • 各种整数类型(int, int8, int16, int32, int64)
  • 各种无符号整数类型(uint, uint8, uint16, uint32, uint64)
  • 浮点类型(float32, float64)
  • 上述数字类型的切片(如[]int, []float64)
  • 布尔类型(bool)
  • 布尔切片([]bool)
  • 字符串(string)
  • 字符串切片([]string)
  • 嵌套结构体
  • net.TCPAddr
  • net.IP
  • time.Duration
  • regexp.Regexp
  • 上述类型的映射(如map[int64]bool, map[string]float64)

标志标签选项

标志默认键名是结构体字段名,但可以在结构体字段的标签值中指定。"flag"键在结构体字段的标签值中是键名,后跟可选的逗号和选项。例如:

// 忽略此字段
Field int `flag:"-"`

// 标志显示为"myName"
Field int `flag:"myName"`

// 如果此字段来自嵌套结构体,则忽略父结构体的前缀
Field int `flag:"~myName"`

// 通过空格后的值设置短名称
// 前缀不会应用于短名称
Field int `flag:"myName a"`

// 此字段将从生成的帮助文本中移除
Field int `flag:",hidden"`

// 此字段将在生成的帮助文本中标记为已废弃
Field int `flag:",deprecated"`

描述标签选项

如果在描述标签(默认为"desc")中指定描述,它将用于USAGE部分。

Addr string `desc:"HTTP host"`

解析函数选项

// DescTag 设置自定义描述标签,默认为"desc"
func DescTag(val string)

// FlagTag 设置自定义标志标签,默认为"flag"
func FlagTag(val string)

// Prefix 设置将应用于所有标志的前缀(如果它们没有标记为~)
func Prefix(val string)

// EnvPrefix 设置将应用于所有环境变量的前缀(如果它们没有标记为~)
func EnvPrefix(val string)

// FlagDivider 设置标志的自定义分隔符,默认为破折号,例如"flag-name"
func FlagDivider(val string)

// EnvDivider 设置环境变量的自定义分隔符
// 默认为下划线,例如"ENV_NAME"
func EnvDivider(val string)

// Validator 设置标志的验证函数
// 检查sflags/validator包中存在的验证器
func Validator(val ValidateFunc)

// 如果不想匿名结构字段被扁平化,设置为false
func Flatten(val bool)

已知问题

  • kingpin不传递布尔参数的值。计数器无法从参数中获取初始值。

类似项目


更多关于golang基于结构体生成多类型命令行标志的插件库sflags的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于结构体生成多类型命令行标志的插件库sflags的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用sflags库基于结构体生成多类型命令行标志

sflags是一个强大的Go库,它允许你通过结构体定义自动生成命令行标志(flags),支持多种数据类型和自定义验证。下面我将详细介绍如何使用sflags。

基本用法

首先安装sflags库:

go get github.com/qwenode/sflags

简单示例

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/qwenode/sflags"
	"github.com/qwenode/sflags/gen/gpflag"
)

type Config struct {
	Host     string `desc:"Server host" default:"localhost"`
	Port     int    `desc:"Server port" default:"8080"`
	Debug    bool   `desc:"Enable debug mode"`
	Timeout  int    `desc:"Request timeout in seconds" default:"30"`
	MaxRetry int    `desc:"Maximum retry attempts" default:"3"`
}

func main() {
	cfg := &Config{}
	
	// 将结构体转换为flag集
	pflagSet, err := gpflag.Parse(cfg)
	if err != nil {
		log.Fatalf("failed to parse flags: %v", err)
	}

	// 解析命令行参数
	pflagSet.Parse(os.Args[1:])

	fmt.Printf("Config: %+v\n", cfg)
}

运行程序时可以使用标准的flag语法:

./app --host=example.com --port=9000 --debug --timeout=60

高级特性

1. 嵌套结构体

type DatabaseConfig struct {
	URL      string `desc:"Database connection URL" default:"postgres://localhost:5432"`
	PoolSize int    `desc:"Connection pool size" default:"10"`
}

type AppConfig struct {
	Server struct {
		Host string `desc:"Server host" default:"0.0.0.0"`
		Port int    `desc:"Server port" default:"8080"`
	}
	DB DatabaseConfig
}

生成的flag会像这样:

--server.host
--server.port
--db.url
--db.pool-size

2. 切片类型支持

type Config struct {
	AllowedIPs []string `desc:"List of allowed IP addresses"`
	Ports      []int    `desc:"List of ports to listen on" default:"80,443"`
}

使用方式:

./app --allowed-ips=192.168.1.1,10.0.0.1 --ports=8080,8081

3. 自定义验证

type Config struct {
	Port int `desc:"Server port" validate:"min=1024,max=65535"`
}

func main() {
	cfg := &Config{}
	
	// 添加验证器
	validator := sflags.NewValidator()
	validator.RegisterFunc("min", func(v interface{}, param string) error {
		// 实现最小值验证
		return nil
	})
	
	_, err := gpflag.Parse(cfg, gpflag.WithValidator(validator))
	// ...
}

4. 环境变量支持

type Config struct {
	APIKey string `desc:"API key" env:"API_KEY"`
}

sflags会自动从环境变量中读取值。

完整示例

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/qwenode/sflags"
	"github.com/qwenode/sflags/gen/gpflag"
)

type ServerConfig struct {
	Host        string   `desc:"Server host" default:"0.0.0.0"`
	Port        int      `desc:"Server port" default:"8080"`
	Enabled     bool     `desc:"Enable server"`
	AllowedCORS []string `desc:"Allowed CORS origins" default:"*"`
}

type DatabaseConfig struct {
	URL      string `desc:"Database URL" env:"DB_URL"`
	Username string `desc:"Database username"`
	Password string `desc:"Database password"`
	PoolSize int    `desc:"Connection pool size" default:"10"`
}

type Config struct {
	Server   ServerConfig
	Database DatabaseConfig
	Debug    bool `desc:"Enable debug mode"`
}

func main() {
	cfg := &Config{}

	// 生成flag集
	pflagSet, err := gpflag.Parse(cfg,
		gpflag.WithEnvPrefix("APP_"), // 环境变量前缀
	)
	if err != nil {
		log.Fatalf("Failed to generate flags: %v", err)
	}

	// 解析命令行参数
	pflagSet.Parse(os.Args[1:])

	// 打印配置
	fmt.Printf("Configuration:\n%+v\n", cfg)

	// 使用帮助标志
	if help, _ := pflagSet.GetBool("help"); help {
		pflagSet.PrintDefaults()
		os.Exit(0)
	}
}

优势总结

  1. 声明式配置:通过结构体定义配置,代码更清晰
  2. 类型安全:自动处理类型转换
  3. 灵活扩展:支持嵌套结构体、切片、自定义类型
  4. 多来源:支持命令行参数、环境变量、默认值
  5. 验证支持:内置验证功能

sflags是一个强大的工具,可以显著简化Go应用程序的配置管理,特别是对于需要复杂配置结构的项目。

回到顶部