了解 Cobra包,使用 cobra 命令行生成一个简单的带子命令的命令行程序。模仿 cobra.Command 编写一个 myCobra 库。

了解 Cobra包,使用 cobra 命令行生成一个简单的带子命令的命令行程序。

首先了解一下cobra的作用

Cobra is a library providing a simple interface to create powerful modern CLI interfaces similar to git & go tools.

Cobra is also an application that will generate your application scaffolding to rapidly develop a Cobra-based application.

参考官方文档https://github.com/spf13/cobra/blob/master/cobra/README.md

 

准备工作

安装cobra执行文件(值得一提,不能直接在apt上面下载。并不能使用,没有--pkg-name 参数)

由于墙的原因,官网上的cobra 文件不能下载,产生报错

 

 

 

 解决:先执行下列代码

 

参考了https://blog.csdn.net/u013256816/article/details/99619335,表示感谢

再安装cobra

 

这样还是不能用,所以我执行了

sudo  apt install cobra 

就可以使用了

但是,注意不可以直接install cobra。不然执行go run main.go时会发生报错。找不到xxx/cmd文件。

 

 

步骤1:

先在创建文件夹cobraPractice

 

命令 makedir cobraPractice

 

步骤二

初始化

 

 

步骤三

创建命令行 执行文件

 

步骤四

简单运行程序

 

接下来实现自己的简单的cobra

 

package myCobra

import (
	"fmt"
	"os"
	flag "github.com/spf13/pflag"
	"strings"
)

var (

)

//command struct have all information about a comand
type Command struct {
	Use string

	Short string
	Long string 
	Run func(cmd *Command, args []string)

	commands []*Command
	choose *Command // sub command at run time

	parent *Command

	args []string

	pflags *flag.FlagSet


}

//add new subCommand to rootCommand 
func (c *Command) AddCommand(sub *Command) {
	for _, v := range c.commands {
		if v == sub {
			return
		}
	}
	c.commands = append(c.commands, sub)
	sub.parent = c
}


//before execute a command 
func (c *Command) Execute() error {
	if  c == nil {
		return fmt.Errorf("Called Execute() on a nil Command")
	}
	if  c .parent == nil { // root Command
		ParseArgs(c, os.Args[1:])
	}
	c.execute()
	return nil
	
}

//execute a command or execute its subCommand
func (c *Command) execute() {
	if c.choose == nil {
		
		c.Run(c, c.args)
		return
	}
	c.choose.execute()
}

//retrieve and store all the args for every command
func ParseArgs(c *Command, args []string) {
	//fmt.Printf("%v", args)
	if len(args) < 1 {
		return
	}
	for _, v := range c.commands {
		if v.Use == args[0] { //there is any sub command fit
			c.args = args[:1]
			c.choose = v
			ParseArgs(v, args[1:])
			return
		}
	}
	c.args = args // there is no sub command, then all args belong to current command
	c.PersistentFlags().Parse(c.args)
}


func (c *Command) PersistentFlags() *flag.FlagSet {
	if c.pflags == nil {
		c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	}
	return c.pflags
}

// Name returns the command's name: the first word in the use line.
func (c *Command) Name() string {
	name := c.Use
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

 

代码解析:

此实现比较简单,例如go run main.go printTxt hello中

root是printTxt的父命令、printTxt是hello的父命令,而且此命令只会执行hello.go

如果有参数的话,也是只能由hello(即没有子命令的命令,拥有参数)

 

func (c *Command) PersistentFlags() *flag.FlagSet {
	if c.pflags == nil {
		c.pflags = flag.NewFlagSet(c.Name(), flag.ContinueOnError)
	}
	return c.pflags
}

// Name returns the command's name: the first word in the use line.
func (c *Command) Name() string {
	name := c.Use
	i := strings.Index(name, " ")
	if i >= 0 {
		name = name[:i]
	}
	return name
}

 上面的函数,就是给命令加上pflag解析参数的功能

 

功能使用:

例如

package cmd

import (
	"fmt"

	//"github.com/spf13/cobra"
	cobra "github.com/wood666/myCobra"
)
var help bool
// printTxtCmd represents the printTxt command
var printTxtCmd = &cobra.Command{
	Use:   "printTxt",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		if (help) {
			fmt.Printf("sorry, We can't give you any help, this is a fake CLI\n")
		}
	},
}

func init() {
	help = true;
	rootCmd.AddCommand(printTxtCmd)
	printTxtCmd.PersistentFlags().BoolVarP(&help, "h", "h", false, "maybe it can give you some help!!!")
}

 在子命令中,调用参数-h

 

 因此运行成功

 

命令生成API,请参考我的上一篇博客

具体代码请参考我的giteehttps://gitee.com/woodx9/go/tree/master/cobra

posted @ 2020-10-30 22:43  woodx  阅读(616)  评论(0)    收藏  举报