浅析go命令行工具 cobra


命令基本结构

cobra可以通过简洁的代码实现一个完善的命令行工具,其内置的函数足以应付大多数场景,下面学习一下cobra的用法。

在使用cobra之前要了解一个命令的基本结构,下面以npm i为例

npm i axios --save-dev
  • i: i就是command本身,在cobra下使用cobra.Command定义,一个command至少会包含User(命令本身),Short(简短描述),Long(完整描述),Run(命令执行时的函数)

  • axios:install命令的参数

  • –save-dev:install命令的flag,flag可以有各种各样的值,常见的是bool。

实现一个简易命令行工具

看完了命令的基本结构下面实现一个简单的命令行工具(这里不会包含具体的功能,只是演示cobra用法)

// 项目结构
.
├── go.mod
├── main.go
|    
├── cmd
    ├── install.go
    └── root.go
//main.go

package main

import "study/cmd"

func main() {
	cmd.Execute()
}

main函数只需要执行cmd包的Execute方法,该方法内部会执行Command.Execute,这是command的核心执行函数。

// root.go
package cmd

import "github.com/spf13/cobra"

//定义npm命令
var rootCmd = &cobra.Command{
	Use: "npm",
	Short: "npm project",
	Long: "npm project",
	Run: func(cmd *cobra.Command, args[]string){
		print("npm...")
	},
}

func Execute(){
	rootCmd.Execute()
}

rootCmd内包含一个npm命令,执行后会调用run方法打印一个string。

函数Execute就是对rootCmd.Execute的包装

此时npm命令已经是可用状态了,执行go build

go build -o npm.exe

npm.exe    // npm...

使用arg和flag

然后添加一个install命令完善以下我们的npm

//install.go

package cmd

import (
	"github.com/spf13/cobra"
	"log"
)

//用来保存flag
var(
	devFlag bool
)

//install命令
var installCmd = &cobra.Command{
	Use: "install",
	Short: "install package",
	Long: "install npm package",
    //arg就是install后面跟着的字符,比如npm i axios,axios就是arg
	Run: func(cmd *cobra.Command, args []string){
		if !devFlag {
			log.Printf("install %s ...", args[0])
		}else{
			log.Printf("install %s as dev dependency", args[0])
		}
	},
}

func init(){
    //AddCommand将install作为root的子命令
	rootCmd.AddCommand(installCmd)
    
    //定义flag,这里的flag是bool类型
	installCmd.Flags().BoolVarP(&devFlag, "save-dev", "D", false, "install dev dependency")
}

在使用install命令后会执行Run方法,通过参数args可以拿到install后面的参数。在init内通过Flags().BoolVarP()定义了一个flag,该flag的值会被写入devFlag。

go build -o npm.exe

npm.exe install axios             // install axios ... 
npm.exe install axios --save-dev  // install axios as dev dependency
npm.exe install axios -D          // install axios as dev dependency

cobra包内的flag分类

在解释flag分类之前先看一下定义一个flag的常见参数(以BoolVarP为例)

  • p *bool:保存该flagValue的内存地址
  • name string:flag 名字,比如前面的save-dev
  • shorthand string:name短格式,定义name后长格式使用–save-dev,短格式就是-D
  • value bool:默认值,如果命令内没传入-D或者–save-dev该值为false
  • usage string:解释该命令作用

是否使用指针接收value

函数名带有var的需要传入一个address接受value

testFlag := installCmd.Flags().Bool("test", false, "test")                          // 没有var,不需要传入bool类型的pointer,这里的testFlag是bool类型的pointer 
installCmd.Flags().BoolVar(&devFlag, "save-dev", false, "install dev dependency")   // 带有var需要使用address接受value

是否支持shortHand

testFlag := installCmd.Flags().BoolP("test", "T", false, "test")    //后面带有P说明支持shortHand,可以使用--test或者-T
testFlag := installCmd.Flags().Bool("test", false, "test")          //不支持shortHand

PersistentFlags

前面定义的flag只能给特定的命令使用(比如给installCmd定义的test),在cobra支持子命令的情况下如果可以给一组命令定义flag可以减少代码量的同时提高维护性,PersistentFlags可以实现此功能

//PersistentFlags
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")

rootCmd定义PersistentFlags后该command的child command都可以使用该flag。


Author: Maple
Reprint policy: All articles in this blog are used except for special statements CC BY 4.0 reprint polocy. If reproduced, please indicate source Maple !
  TOC