DevOpsCamp第2期:从 《cobra - 06 持久化命令》 开始聊聊 Go语言 指针类型的使用注意事项
DevOpsCamp第2期:从 《cobra - 06 持久化命令》 开始聊聊 Go语言 指针类型的使用注意事项
如果在 公众号 文章发现状态为 已更新, 建议点击 查看原文 查看最新内容。
状态: 未更新
原文链接: https://typonotes.com/posts/2023/02/19/devopscamp-cobra-06-persistent-run-and-flags/
嗯, 在 cobra 中提供了一种叫做 Persistent
的 状态, 定向支持 函数 与 参数。
下面这段代码是是使用时的定义。
|
|
凡是定义了 Persistent
Run(1) 和 Flag(2) 的节点, 其子孙节点都会 继承 这种状态。 这种状态也可以被子孙节点的自定义状态覆盖。
注意: 这种状态是继承自 其父节点, 而非 上级节点 。
父节点不是上级节点
这个的问题的发生原因, 还是在 xxx.AddCommand
的时候造成的。 因为 &cobra.Command{}
是指针对象/引用对象, 因此在不同的地方修改是会全局影响的。 这个是基础知识, 也是重要的 坑 点, 需要牢记。
下面是一个代码案例, 帮助理解。
案例代码在在 Github: https://github.com/tangx-labs/cobra06-demo
代码中实现了一个如下图所示的 命令树 结构。 其中 sub2
同时挂载到了 root
和 sub1
节点。
以下是代码执行结果执行结果, 注意看
--config
的参数值PersistentPreRun
的执行结果sub2
的Usage
路径, 无论从哪里进入, 都是root sub1 sub2
。
代码执行过程
./cobra-demo6
|
|
./cobra-demo6 sub1
|
|
./cobra06-demo sub2
|
|
./cobra06-demo sub1 sub2
|
|
引用类型回顾
首先, 我们再来回顾一下一下 Cobra Command
的结构体
|
|
可以看到, parent *Command
是指针类型。 这意味着, 在任何地方修改都会影响全局引用。
这里简单的回顾一下 引用对象。 A, B, C 都指向 指针地址, 而 指针地址 纸箱 真实数据地址。 当因为某个外力修改了 真实数据地址 中的内容的时候, 虽然 A, B, C 都没变化, 但是他们 取 到的东西发生了变化。
举个例子,
- 你去温泉之前寄存物品, 商家会给你一个 手牌(指针地址), 你拿着手牌将 名贵手表(数据) 放入对应的 100号柜子(真实地址)。
- 在你泡温泉的时候, 某个人(外力) 打开了柜子, 把你的手表换成了 塑料手表(数据修改)。
- 等你回来的时候, 虽然你的手牌没变, 但是你打开柜子的时候, 你拿到的不再你期望的东西了。
而正好, 每次执行 xxx.AddCommand(children)
添加子命令的时候, children
节点的 parent
字段都会被修改。
|
|
当一个节点, 重复被假如到其他节点的时候, 会出现这个问题。
cobra 树实现过程解析
下面, 我们对命令树的实现过程进行拆分。 注意 每个节点分为上下两层, 上层 表示父节点的名称, 下层 表示当前节点。
parent
----------
node
当执行第一条命令时时候, 此时创建的命令树就有所差异了。 左侧时从 root
开始, 右侧是从 sub1
开始。
当执行的第二条命令的时候, 都实现了相同结构的命令树(不看父节点差异的话)。
但仔细分析其内部节点, 可以知道, 相同位置的节点, 其父节点不一样。
- 原文链接:https://typonotes.com/posts/2023/02/19/devopscamp-cobra-06-persistent-run-and-flags/
- 本文为原创文章,转载注明出处。
- 欢迎 扫码关注公众号
Go与云原生
或 订阅网站 https://typonotes.com/ 。 - 第一时间看后续精彩文章。觉得好的话,请猛击文章右下角「在看」,感谢支持。