了解 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

posted @   woodx  阅读(582)  评论(0编辑  收藏  举报
编辑推荐:
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
阅读排行:
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
点击右上角即可分享
微信分享提示