DevopsCamp(第二期) 《05 Cobra 的子命令》与《cobra命令树和gin路由树的实现差异》
原文链接: https://typonotes.com/posts/2...
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 // ???
// 省略
}
}
我们可以在任意节点调用 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()
}
}
这种感觉, 特别像 环太平洋2 中的那个机械老鼠, 不仅可以独立执行命令, 还可以把大型怪兽“缝合”在一起。
总体来说, cobra 命令节点 独立而又统一
gin 的路由树
与 cobra 相比, gin 的路由树实现就是另外一种方式了, 我称之为 生长。 换句话说, gin 路由的子节点不能独立于父节点 单独 定义。
// 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
方法的时候,
- 必须 要传入 子节点 的相对路径
- 使用私有方法计算出
basePath
的值。
这个特别像怀孕生孩子, 一代接一代。 绝对错不了。 O.o
。
gin 的 RouterGroup 能实现 认亲/挂靠 模式吗?
肯定可以, 做个变形手术就好了。 这里挖个坑吧。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。