Golang 的 cobra 是如何实现使用链表实现命令树的

Golang 的 cobra 是如何实现使用链表实现命令树的

在 cobra 中, 每个 命令 都是独立的。 通过 parent.AddCommand(children) 的形式进行串连。

var root = &cobra.Command{}

var child = &cobra.Command{}

func init() {
    root.AddCommand(child)
}

没了, 应用上就这么多。

cobra 命令树

如果你用过 gin 的路由树的话, 可能会对 cobra 的命令树实现更为深刻。

删除多余的结构, cobra 节点 就是下面这样的。

type Command struct {
    // 子命令
    commands []*Command
    // 父命令
    parent *Command
}

当进行 命令树 组合的时候, 是通过 领养/挂靠 的方式实现的。

// AddCommand adds one or more commands to this parent command.
func (c *Command) AddCommand(cmds ...*Command) {
    for i, x := range cmds {
        if cmds[i] == c {
            panic("Command can't be a child of itself")
        }

        // 为子命令设置父命令(认亲)
        cmds[i].parent = c // (1)
// 省略
        // 添加传入的子命令
        c.commands = append(c.commands, x) // (2)
    }
}

(1) 在我们可以在任意节点调用 Execute 方法, 这个调用会通过 递归 找到最上层的 节点。

func (c *Command) Execute() error {
    _, err := c.ExecuteC()
    return err
}

// ExecuteC executes the command.
func (c *Command) ExecuteC() (cmd *Command, err error) {
    // Regardless of what command execute is called on, run on Root only
    // 递归寻找最上层
    if c.HasParent() {
        return c.Root().ExecuteC()
    }
}

再来看一次 Command 结构体定义

type Command struct {
    // 子命令
    commands []*Command
    // 父命令
    parent *Command
}

(2) 通过将传入的命令保存到 []*Command 切片中, 实现了命令树的 组合

c.commands = append(c.commands, x) // (2)

且同时 实现了 同一个命令挂载到多个父命令上

root.AddCommand(sub1, sub2) // (a)
sub1.AddCommand(sub2) // (b)

commands 是一个切片, 用于保存 挂载 上来的子命令。 但是, 这里需要注意, 由于 *Command 是指针类型, 意味着在任何修改, 都可能影响其他调用的地方。

对于 sub2 而言, (a)处父节点是 root(b)处父节点是 sub1最终父节点是 sub1。 但不影响 sub2 同时是 rootsub1 的子命令。

总体来说, cobra 命令节点 独立而又统一

互相吹捧, 共同进步

欢迎和我一起学习进步, 如果有什么问题, 可以给我私信留言。 或者

  1. 加我好友 线下讨论。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值