golang基于结构体自动生成CLI应用参数配置插件库commandeer的使用

Golang基于结构体自动生成CLI应用参数配置插件库Commandeer的使用

Commandeer简介

Commandeer是一个基于结构体自动生成命令行参数的Go库,它可以根据结构体字段和标签自动设置命令行标志。

Commandeer示例图片

主要特点

  • 将Go应用开发为库,保持main包简洁
  • 自动保持命令行参数与代码同步
  • 使用结构体字段注释作为帮助信息
  • 最小化依赖污染,仅使用标准库

快速开始示例

1. 定义应用结构

package myapp

import "fmt"

type Main struct {
    Num     int    `help:"How many does it take?"`  // 数字参数,help标签提供帮助信息
    Vehicle string `help:"What did they get?"`      // 字符串参数
}

// 构造函数,设置默认值
func NewMain() *Main { return &Main{Num: 5, Vehicle: "jeep"} }

// 应用主逻辑
func (m *Main) Run() error {
    if m.Num < 2 || m.Vehicle == "" {
        return fmt.Errorf("Need more gophers and/or vehicles.")
    }
    fmt.Printf("%d gophers stole my %s!\n", m.Num, m.Vehicle)
    return nil
}

2. 创建main包

package main

import (
    "fmt"
    "github.com/jaffee/commandeer"
    "github.com/jaffee/commandeer/examples/myapp"
)

func main() {
    // 使用commandeer运行应用
    err := commandeer.Run(myapp.NewMain())
    if err != nil {
        fmt.Println(err)
    }
}

3. 使用示例

$ ./myapp -h
Usage of ./myapp:
  -num int
        How many does it take? (default 5)
  -vehicle string
        What did they get? (default "jeep")

$ ./myapp
5 gophers stole my jeep!
$ ./myapp -num 3 -vehicle horse
3 gophers stole my horse!

高级功能

自定义标志名称

使用flag标签覆盖默认生成的标志名称:

type Main struct {
    Num     int    `flag:"number"`  // 使用-number而不是默认的-num
}

忽略字段

使用flag:"-"忽略结构体字段:

type Main struct {
    Num     int    `flag:"-"`  // 该字段不会生成命令行参数
}

嵌套结构体

嵌套结构体默认使用点号连接字段名:

type Main struct {
    Vehicle struct {
        Color string
        Weight int
    }
}

生成的标志:

-vehicle.color string
-vehicle.weight int

嵌入结构体字段

使用flag:"!embed"将嵌套结构体字段提升到顶层:

type Main struct {
    Vehicle struct {
        Color string
        Weight int
    } `flag:"!embed"`
}

生成的标志:

-color string
-weight int

Cobra集成

如果你不介意外部依赖,可以使用github.com/jaffee/commandeer/cobrafy集成Cobra和pflag,提供GNU/POSIX风格的标志和其他特性。

总结

Commandeer是一个简单而强大的库,可以自动从结构体生成命令行参数,减少样板代码,保持参数与代码同步。它特别适合那些希望将主要逻辑放在库中,而保持main包简洁的开发者。


更多关于golang基于结构体自动生成CLI应用参数配置插件库commandeer的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang基于结构体自动生成CLI应用参数配置插件库commandeer的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用Commandeer自动生成Golang CLI应用参数配置

Commandeer是一个优秀的Go语言库,它能够基于结构体自动生成命令行接口(CLI)应用的参数配置。下面我将详细介绍如何使用Commandeer来简化CLI应用的开发。

基本概念

Commandeer通过结构体标签(struct tags)自动将结构体字段映射到命令行参数,无需手动编写参数解析代码。它支持:

  • 自动生成帮助信息
  • 支持子命令
  • 环境变量绑定
  • 配置文件支持
  • 参数验证

安装

go get github.com/object88/commandeer

基础用法

1. 定义配置结构体

package main

import (
	"fmt"
	"log"
	
	"github.com/object88/commandeer"
)

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

2. 创建并运行CLI应用

func main() {
	cfg := &Config{}
	
	// 使用Commandeer解析命令行参数
	err := commandeer.Run(cfg, func() error {
		// 这里是应用的主要逻辑
		fmt.Printf("Starting server on %s:%d (Debug: %v, Timeout: %ds)\n",
			cfg.Host, cfg.Port, cfg.Debug, cfg.Timeout)
		return nil
	})
	
	if err != nil {
		log.Fatal(err)
	}
}

高级特性

子命令支持

type RootConfig struct {
	GlobalFlag string `help:"Global flag for all commands"`
}

type StartConfig struct {
	Port int `help:"Port to listen on" default:"8080"`
}

type StopConfig struct {
	Force bool `help:"Force stop"`
}

func main() {
	root := &RootConfig{}
	start := &StartConfig{}
	stop := &StopConfig{}
	
	p := commandeer.NewProgram(root)
	p.AddCommand("start", "Start the server", start, func() error {
		fmt.Printf("Starting on port %d (Global: %s)\n", start.Port, root.GlobalFlag)
		return nil
	})
	p.AddCommand("stop", "Stop the server", stop, func() error {
		fmt.Printf("Stopping (Force: %v, Global: %s)\n", stop.Force, root.GlobalFlag)
		return nil
	})
	
	if err := p.ParseAndRun(); err != nil {
		log.Fatal(err)
	}
}

环境变量绑定

type Config struct {
	DatabaseURL string `help:"Database connection URL" env:"DB_URL"`
	APIKey      string `help:"API key" env:"API_KEY"`
}

配置文件支持

type Config struct {
	Server struct {
		Host string `yaml:"host" help:"Server host"`
		Port int    `yaml:"port" help:"Server port"`
	} `yaml:"server"`
	
	Logging struct {
		Level string `yaml:"level" help:"Log level" default:"info"`
	} `yaml:"logging"`
}

func main() {
	cfg := &Config{}
	
	// 添加配置文件支持
	p := commandeer.NewProgram(cfg)
	p.WithConfigFile("config.yaml", "Path to config file")
	
	err := p.ParseAndRun(func() error {
		fmt.Printf("Server: %s:%d, Log Level: %s\n", 
			cfg.Server.Host, cfg.Server.Port, cfg.Logging.Level)
		return nil
	})
	
	if err != nil {
		log.Fatal(err)
	}
}

验证参数

type Config struct {
	Port int `help:"Port number" validate:"min=1024,max=65535"`
}

func main() {
	cfg := &Config{}
	
	p := commandeer.NewProgram(cfg)
	p.WithValidation() // 启用验证
	
	err := p.ParseAndRun(func() error {
		fmt.Printf("Using port: %d\n", cfg.Port)
		return nil
	})
	
	if err != nil {
		log.Fatal(err)
	}
}

自定义帮助信息

type Config struct {
	// ... 其他字段 ...
}

func main() {
	cfg := &Config{}
	
	p := commandeer.NewProgram(cfg)
	p.WithDescription("My Awesome CLI Tool")
	p.WithVersion("1.0.0")
	p.WithExamples([]string{
		"  tool --host example.com --port 9090",
		"  tool --help",
	})
	
	err := p.ParseAndRun(func() error {
		// 应用逻辑
		return nil
	})
	
	if err != nil {
		log.Fatal(err)
	}
}

实际应用示例

package main

import (
	"fmt"
	"log"
	"time"
	
	"github.com/object88/commandeer"
)

type ServerConfig struct {
	Host         string        `help:"Server host" default:"0.0.0.0"`
	Port         int           `help:"Server port" default:"8080"`
	ReadTimeout  time.Duration `help:"Read timeout" default:"30s"`
	WriteTimeout time.Duration `help:"Write timeout" default:"30s"`
	Debug        bool          `help:"Enable debug mode"`
}

func main() {
	cfg := &ServerConfig{}
	
	p := commandeer.NewProgram(cfg)
	p.WithDescription("HTTP Server Application")
	p.WithVersion("1.2.3")
	
	err := p.ParseAndRun(func() error {
		startServer(cfg)
		return nil
	})
	
	if err != nil {
		log.Fatal(err)
	}
}

func startServer(cfg *ServerConfig) {
	fmt.Printf("Starting server on %s:%d\n", cfg.Host, cfg.Port)
	fmt.Printf("Timeouts - Read: %v, Write: %v\n", cfg.ReadTimeout, cfg.WriteTimeout)
	fmt.Printf("Debug mode: %v\n", cfg.Debug)
	
	// 实际服务器启动代码...
}

Commandeer极大地简化了Golang CLI应用的开发,通过结构体定义自动生成命令行参数解析,减少了样板代码,同时提供了丰富的功能如子命令、环境变量绑定、配置文件支持和参数验证等。这使得开发者可以更专注于业务逻辑的实现,而不是参数解析的细节。

回到顶部