(四)子命令

Last Modified: 2023/08/13

前言

在前面的文章中,我们介绍了如何利用 cobra 框架编写命令行程序,以及如何给命令行程序定义选项,已经忘记了的同学可以重温之前的内容:

今天我们的内容是如何实现子命令。

子命令的例子

会 java 的同学,肯定对 mvn 命令不陌生,它是构建 java 程序最常用的工具之一。 mvn 包含多个子命令:

mvn clean
mvn compile
mvn package

这里的 cleancompilepackage 都是 mvn 这个命令下的子命令。 子命令可以看作是一种组织命令的方式,将多个相关的子命令组织到一个大的命令下。

再举个例子,npm 命令,通过 npm -h 可以看出该命令下包含 N 多个子命令。

教程目标

我们要实现查指定目录下的指定文件名称开头的文件。例如,查找 /tmp 目录下的前缀是 x 的文件名称。

于是我们实现一个子命令 search, 同时定义两个命令行选项:-p 用于指定前缀,-d 用于指定目标查找目录(即在该目录下查找)。

./list search -p x -d /tmp
# 或者通过长选项名称方式
./list search --prefix=x --directory=/tmp

实现 search 子命令

为了实现 search 子命令,我们打算分为以下几步:

  • 1、利用 cobra-cli 生成 search 子命令,并修改 search 子命令的帮助信息;
  • 2、定义 search 子命令的命令行选项 -d-p
  • 3、获取命令行选项的值,同时实现 search 子命令的业务逻辑。

步骤1 - 生成子命令

进入项目工作目录,使用 cobra-cli 命令添加 search 子命令。

cobra-cli add search

命令执行完毕后,在项目根目录下的 cmd/ 目录下 多了一个 search.go,该文件就是我们实现 search 子命令逻辑的地方。

下面就是生成的 search.go 文件中的代码,由于篇幅关系删除了一些注释,并且我们修改了帮助信息:

var searchCmd = &cobra.Command{
	Use:   "search",
	Short: "查找指定目录下指定前缀开头的文件",
	Long: `查找指定目录下指定前缀开头的文件。`,
	Run: func(cmd *cobra.Command, args []string) {
		// 这里实现命令逻辑
	},
}
func init() {
	rootCmd.AddCommand(searchCmd)
	// searchCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

步骤2 - 定义选项

相信看过前面两篇文章的同学,这一步应该是轻车熟路,我们直接给出代码:

func init() {
	rootCmd.AddCommand(searchCmd)
	searchCmd.Flags().StringP("prefix", "p", "", "待查找的文件名前缀")
	searchCmd.Flags().StringP("directory", "d", "", "目标查找目录")
}

步骤3 - 实现子命令逻辑

子命令的逻辑我们打算定义一个函数 searchByPrefix 来实现,在该调用函数之前,我们获取选项的值,并将选项的值作为函数的入参。

prefix, _ := cmd.Flags().GetString("prefix")
dir, _ := cmd.Flags().GetString("directory")
searchByPrefix(dir, prefix)

剩下的就是 searchByPrefix 函数的实现。无非就是利用 strings.HasPrefix 检查文件名称是否以指定前缀开头,这个过于简单,直接指出代码:

func searchByPrefix(dir string, prefix string) {
	files, _ := ioutil.ReadDir(dir)
	fileNames := make([]string, 0, len(files))
	for _, file := range files {
		if strings.HasPrefix(file.Name(), prefix) {
			fileNames = append(fileNames, file.Name())
		}
	}
	fmt.Println(strings.Join(fileNames, "\n"))
}

完整代码放在 github 上,戳这里查看。或者 clone 整个 list 项目,切换到 easy-command-part4 分支查看。

牛刀小试

让我们来查找下 /tmp 目录下以 s 开头的文件名称。

go run main.go search -d /tmp -p s

#或者先编译出我们的 list 命令行程序
go build
./list search -d /tmp -p s

结语

本篇中,我们介绍了如何利用 cobra-cli 给命令添加子命令,我们以 search 子命令说明了实现方法。值得一提的是,大家可以发挥想象力给 list 添加更多的子命令。

有问题吗?点此反馈!

温馨提示:反馈需要登录