了解 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 | 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(即没有子命令的命令,拥有参数)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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解析参数的功能
功能使用:
例如
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | 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
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」