前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >DevOpsCamp 第 2 期作业: 《cobra - 05 子命令》 说下 cobra 命令树和 gin 路由树的实现差异

DevOpsCamp 第 2 期作业: 《cobra - 05 子命令》 说下 cobra 命令树和 gin 路由树的实现差异

作者头像
老麦
发布2023-02-25 20:04:13
3570
发布2023-02-25 20:04:13
举报
文章被收录于专栏:Go与云原生Go与云原生

DevOpsCamp 第 2 期作业: 《cobra - 05 Cobra 的子命令》 简单说下 cobra 命令树和 gin 路由树的实现差异

原文链接: https://typonotes.com/posts/2023/02/14/devopscamp-cobra-05-subcommand/

cobra 的子命令

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

代码语言:javascript
复制
var root = &cobra.Command{}

var child = &cobra.Command{}

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

没了, 应用上就这么多。

cobra 命令树

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

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

代码语言:javascript
复制
type Command struct {
    // 子命令
    commands []*Command
    // 父命令
    parent *Command
}

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

代码语言:javascript
复制
// 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 // ???
// 省略
    }
}

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

代码语言:javascript
复制
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()
    }
}

这种感觉, 特别像 环太平洋2 中的那个机械老鼠, 不仅可以独立执行命令, 还可以把大型怪兽“缝合”在一起。

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

gin 的路由树

与 cobra 相比, gin 的路由树实现就是另外一种方式了, 我称之为 生长。换句话说, gin 路由的子节点不能独立于父节点 单独 定义。

代码语言:javascript
复制
// Group creates a new router group. You should add all the routes that have common middlewares or the same path prefix.
// For example, all the routes that use a common middleware for authorization could be grouped.
func (group *RouterGroup) Group(relativePath string, handlers ...HandlerFunc) *RouterGroup {
    return &RouterGroup{
        Handlers: group.combineHandlers(handlers),
        basePath: group.calculateAbsolutePath(relativePath),
        engine:   group.engine,
    }
}

从上面代码可以看出来, RouterGroup 是通过 Group 方法实现路由节点 生长 的, 在调用 Group 方法的时候,

  1. 必须 要传入 子节点 的相对路径
  2. 使用私有方法计算出 basePath 的值。

这个特别像怀孕生孩子, 一代接一代。绝对错不了。O.o

gin 的 RouterGroup 能实现 认亲/挂靠 模式吗?

肯定可以, 做个变形手术就好了。这里挖个坑吧。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2023-02-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 熊猫云原生Go 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • DevOpsCamp 第 2 期作业: 《cobra - 05 Cobra 的子命令》 简单说下 cobra 命令树和 gin 路由树的实现差异
    • cobra 的子命令
      • cobra 命令树
        • gin 的路由树
          • gin 的 RouterGroup 能实现 认亲/挂靠 模式吗?
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档