我无法为将具有 n 命令的CLI工具创建结构。每个命令可以具有 n 个子命令,每个子命令可以具有 n 个子命令。
我的问题是,在Go语言中,我正在努力寻找一种创建递归函数的方法,以输出每个命令的名称以及每个 n 子命令+每个 n 该子命令的子命令,在完整列表中。
例如,我希望获得以下输出:
1. command1
2. command2
3. command3
4. command3 subcommand1
5. command3 subcommand1 subcommand1
6. command3 subcommand2
这是我的代码:
package main
import (
"fmt"
)
type command struct {
name string
parent *command
subcommands []*command
}
func getLastCommand(c command) command {
for _, s := range c.subcommands {
if len(s.subcommands) == 0 {
return *s
}
return getLastCommand(*s)
}
return c
}
func main() {
cmdBase1 := command{
name: "base1",
}
cmdBase2 := command{
name: "base2",
}
var (
cmdBase3,
cmdBase3Sub1,
cmdBase3Sub1Sub1,
cmdBase3Sub2 command
)
cmdBase3 = command{
name: "base3",
subcommands: []*command{&cmdBase3Sub1, &cmdBase3Sub2},
}
cmdBase3Sub1 = command{
name: "base3:sub1",
parent: &cmdBase3,
subcommands: []*command{&cmdBase3Sub1Sub1},
}
cmdBase3Sub1Sub1 = command{
name: "base3:sub1:sub1",
parent: &cmdBase3Sub1,
}
cmdBase3Sub2 = command{
name: "base3:sub2",
parent: &cmdBase3,
}
// root commands
commands := []command{
cmdBase1,
cmdBase2,
cmdBase3,
}
for _, c := range commands {
last := getLastCommand(c)
fmt.Println(last.name)
}
}
https://play.golang.org/p/HZPRlSghfAY
以下是当前输出:
base1
base2
base3:sub1:sub1
我想要的输出与上面的代码是:
base1
base2
base3
base3:sub1
base3:sub1:sub1
base3:sub2
我需要在代码中进行哪些更改,以便获得高于期望的输出?有没有我可以遵循的算法或数据结构来解决这个问题?我尝试了深度优先和二进制搜索,但是似乎无法将其塑造到我的结构中。
答案 0 :(得分:3)
一个简单而优雅的解决方案是使用verbose_name_plural
方法“武装” command
。这可以打印其名称,并覆盖其子命令,并调用其print()
(执行相同的操作):
print()
然后在func (c *command) print() {
fmt.Println(c.name)
for _, sc := range c.subcommands {
sc.print()
}
}
中打印命令只是调用其main()
方法(甚至不需要/使用print()
):
getLastCommand()
这将产生所需的输出(在Go Playground上尝试):
for _, c := range commands {
c.print()
}
请注意,当然base1
base2
base3
base3:sub1
base3:sub1:sub1
base3:sub2
不必一定是方法,它也可以是常规函数,在这种情况下,它看起来可能像这样:
print()
还有func print(c *command) {
fmt.Println(c.name)
for _, sc := range c.subcommands {
print(sc)
}
}
中的循环:
main()
结果相同,请在Go Playground上尝试一下。
我也建议保持一致。如果您决定使用指向for _, c := range commands {
print(&c)
}
的指针,请在各处使用它(例如command
中的commands
切片存储非指针),这就是为什么必须将其元素地址传递给{ {1}}。