golang简单实用的命令行工具插件库acmd的使用

Golang简单实用的命令行工具插件库acmd的使用

acmd是一个简单、实用且固执己见的Go语言CLI包。它提供了简洁的API和良好的默认值,非常适合快速构建命令行工具。

特点

  • 简单易用的API
  • 无依赖
  • 干净且经过测试的代码
  • 支持命令别名
  • 自动建议命令
  • 内置helpversion命令

安装

Go 1.17+版本可以使用以下命令安装:

go get github.com/cristalhq/acmd

使用示例

下面是一个完整的示例,展示如何使用acmd创建命令行工具:

package main

import (
	"context"
	"fmt"
	"time"

	"github.com/cristalhq/acmd"
)

func main() {
	// 获取当前时间
	now := time.Now()

	// 定义命令列表
	cmds := []acmd.Command{
		{
			Name:        "now",  // 命令名称
			Description: "打印当前时间", // 命令描述
			ExecFunc: func(ctx context.Context, args []string) error {
				// 执行命令的逻辑
				fmt.Printf("当前时间: %s\n", now.Format("15:04:05"))
				return nil
			},
		},
		{
			Name:        "status",  // 命令名称
			Description: "打印系统状态", // 命令描述
			ExecFunc: func(ctx context.Context, args []string) error {
				// 可以在这里使用ctx
				fmt.Println("系统状态: 运行正常")
				return nil
			},
		},
	}

	// 创建Runner,所有acmd.Config字段都是可选的
	r := acmd.RunnerOf(cmds, acmd.Config{
		AppName:        "acmd-example",  // 应用名称
		AppDescription: "acmd包使用示例",  // 应用描述
		Version:        "v1.0.0",       // 版本号
		// Context - 如果为nil,将使用signal.Notify
		// Args - 如果为nil,将使用os.Args[1:]
		// Usage - 如果为nil,将使用默认打印
	})

	// 运行命令
	if err := r.Run(); err != nil {
		r.Exit(err)
	}
}

运行示例

编译并运行上述代码:

# 编译
go build -o example

# 查看帮助
./example help

# 运行now命令
./example now

# 运行status命令
./example status

总结

acmd提供了一个简单而强大的方式来构建命令行工具,避免了复杂框架的学习曲线。它的主要优势在于:

  1. 简洁明了的API设计
  2. 零外部依赖
  3. 内置常用功能(帮助、版本等)
  4. 良好的默认配置

对于需要快速开发命令行工具的场景,acmd是一个非常不错的选择。


更多关于golang简单实用的命令行工具插件库acmd的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang简单实用的命令行工具插件库acmd的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


acmd - 简单实用的Golang命令行工具插件库

acmd是一个轻量级的Golang命令行工具库,它提供了简单易用的API来构建命令行应用程序。下面我将介绍acmd的基本用法和示例代码。

安装

go get github.com/cristalhq/acmd

基本用法

1. 创建简单命令

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/cristalhq/acmd"
)

func main() {
	// 定义命令
	cmds := []acmd.Command{
		{
			Name:        "hello",
			Description: "打印欢迎信息",
			ExecFunc: func(ctx acmd.Context) error {
				fmt.Println("Hello, World!")
				return nil
			},
		},
	}

	// 配置运行器
	r := acmd.RunnerOf(cmds, acmd.Config{
		AppName:        "myapp",
		AppDescription: "一个简单的命令行应用",
		Version:        "v1.0.0",
		Args:           os.Args[1:],
	})

	// 运行命令
	if err := r.Run(); err != nil {
		log.Fatal(err)
	}
}

2. 带参数的命令

cmds := []acmd.Command{
	{
		Name:        "greet",
		Description: "向某人问好",
		ExecFunc: func(ctx acmd.Context) error {
			if len(ctx.Args) == 0 {
				return fmt.Errorf("请提供要问候的人名")
			}
			fmt.Printf("Hello, %s!\n", ctx.Args[0])
			return nil
		},
	},
}

3. 子命令

cmds := []acmd.Command{
	{
		Name:        "user",
		Description: "用户管理",
		SubCommands: []acmd.Command{
			{
				Name:        "add",
				Description: "添加用户",
				ExecFunc: func(ctx acmd.Context) error {
					if len(ctx.Args) < 2 {
						return fmt.Errorf("需要提供用户名和邮箱")
					}
					fmt.Printf("添加用户: 用户名=%s 邮箱=%s\n", ctx.Args[0], ctx.Args[1])
					return nil
				},
			},
			{
				Name:        "list",
				Description: "列出用户",
				ExecFunc: func(ctx acmd.Context) error {
					fmt.Println("用户列表:")
					fmt.Println("- Alice")
					fmt.Println("- Bob")
					return nil
				},
			},
		},
	},
}

4. 标志(flags)支持

cmds := []acmd.Command{
	{
		Name:        "serve",
		Description: "启动服务",
		ExecFunc: func(ctx acmd.Context) error {
			// 创建flag集
			fs := flag.NewFlagSet("serve", flag.ContinueOnError)
			port := fs.Int("port", 8080, "服务监听端口")
			debug := fs.Bool("debug", false, "启用调试模式")
			
			// 解析flags
			if err := fs.Parse(ctx.Args); err != nil {
				return err
			}
			
			fmt.Printf("启动服务: 端口=%d 调试模式=%v\n", *port, *debug)
			return nil
		},
	},
}

高级特性

1. 自定义帮助信息

r := acmd.RunnerOf(cmds, acmd.Config{
	AppName:        "myapp",
	AppDescription: "一个高级命令行应用",
	Version:        "v1.0.0",
	Args:           os.Args[1:],
	// 自定义帮助模板
	HelpOptions: acmd.HelpOptions{
		Template: `{{.AppName}} - {{.AppDescription}}

版本: {{.Version}}

用法:
  {{.AppName}} [命令] [参数]

命令:
{{range .Commands}}  {{.Name}}\t{{.Description}}
{{end}}

使用 "{{.AppName}} [命令] --help" 获取命令详情
`,
	},
})

2. 错误处理

cmds := []acmd.Command{
	{
		Name:        "divide",
		Description: "除法运算",
		ExecFunc: func(ctx acmd.Context) error {
			if len(ctx.Args) != 2 {
				return acmd.ErrorWithUsage{
					Err: fmt.Errorf("需要提供两个数字参数"),
					Cmd: ctx.Command,
				}
			}
			
			a, err := strconv.Atoi(ctx.Args[0])
			if err != nil {
				return fmt.Errorf("第一个参数必须是数字")
			}
			
			b, err := strconv.Atoi(ctx.Args[1])
			if err != nil {
				return fmt.Errorf("第二个参数必须是数字")
			}
			
			if b == 0 {
				return fmt.Errorf("除数不能为零")
			}
			
			fmt.Printf("结果: %d\n", a/b)
			return nil
		},
	},
}

完整示例

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/cristalhq/acmd"
)

func main() {
	cmds := []acmd.Command{
		{
			Name:        "hello",
			Description: "打印欢迎信息",
			ExecFunc: func(ctx acmd.Context) error {
				fmt.Println("Hello, World!")
				return nil
			},
		},
		{
			Name:        "calc",
			Description: "计算器",
			SubCommands: []acmd.Command{
				{
					Name:        "add",
					Description: "加法",
					ExecFunc: func(ctx acmd.Context) error {
						if len(ctx.Args) < 2 {
							return fmt.Errorf("需要至少两个数字")
						}
						sum := 0
						for _, arg := range ctx.Args {
							num, err := strconv.Atoi(arg)
							if err != nil {
								return fmt.Errorf("无效数字: %s", arg)
							}
							sum += num
						}
						fmt.Printf("总和: %d\n", sum)
						return nil
					},
				},
			},
		},
	}

	r := acmd.RunnerOf(cmds, acmd.Config{
		AppName:        "myapp",
		AppDescription: "多功能命令行工具",
		Version:        "v1.0.0",
		Args:           os.Args[1:],
	})

	if err := r.Run(); err != nil {
		log.Printf("错误: %v\n", err)
		os.Exit(1)
	}
}

总结

acmd是一个简单实用的Golang命令行工具库,它具有以下特点:

  1. 轻量级且易于使用
  2. 支持子命令和参数
  3. 内置帮助系统
  4. 可自定义帮助模板
  5. 良好的错误处理机制

对于需要快速构建命令行工具的场景,acmd是一个不错的选择。它比标准库flag更灵活,又不像cobra那么复杂,非常适合中小型命令行应用开发。

回到顶部