01.26 Go 編程:寫一個程序友好的命令行工具包

以下文章來源於一艘慢船 ,作者JayL


Go 編程:寫一個程序友好的命令行工具包

作為一名後端程序員,命令行程序太普遍了。如何開始一個類似的命令行程序的工具以及相關依賴包也非常多。個人最常使用的工具包是: spf13/cobra。 同時結合作者提供的spf13/viper包,命令行程序需要的絕大部分功能作者都替你想到了,基本上是沒有必要重寫一個新輪子了。

然而,即便是功能再齊全的包在個人使用的習慣與便利上還是因人而異的。雖然,通過cobra提供的命令行工具可以快速的啟動一個命令行項目的框架代碼,但是在多級命令的組織上,還可以在簡潔一點,特別是對於子命令的操作,添加一個子命令必須指定對應的父級命令,邏輯上正確,但是使用上是不便的。

<code>rootCmd.AddCommand(subCmd)
...
subCmd.AddCommand(subSubCmd)/<code>

cobra生成的代碼中,不難發現類似以上的代碼。在多級命令的組織上是非常機械。因為是生成代碼,不需要手動編輯代碼,所以這種不便很難直接感受到。但它提供的cobra工具是程序員友好的。

但是對於企業級命令行項目而言,不可能通過人工的方式通過cobra工具手動生成相應的命令行框架代碼。而是需要直接將命令行代碼集成的項目框架中去,所以就命令行相關代碼而言,我們需要更加程序友好的工具包。

一個理想的命令行工具包,我認為可以是這樣的:

整個包僅提供一個增加子命令的接口:Add, 通過option的方式,對具體命令行進行配置即可。特別是對於多級命令的設置上,我希望可以通過類似文件系統的目錄結構的形式來定義具體的子級命令。

<code>/\t\t\t根命令
/foo\t\t一級命令
/foo/bar \t二級命令
.../<code>

在使用上,可以是這樣:

根命令行:

<code>import (
"fmt"

"github.com/x-mod/cmd"
)

func main() {
\tcmd.Add(
\t\tcmd.Path("/"),
\t\tcmd.Main(Main),
)
\tcmd.Execute()
}

func Main(c *cmd.Command, args []string) error {
\tfmt.Println("my root command running ...")
\treturn nil
}/<code>

多級命令行:

<code>import (
"fmt"


"github.com/x-mod/cmd"
)

func main() {
\tcmd.Add(
\t\tcmd.Path("/foo/bar/v1"),
\t\tcmd.Main(V1),
).PersistentFlags().StringP("parameter", "p", "test", "flags usage")
\tcmd.Version("version string")
\tcmd.Execute()
}

func V1(c *cmd.Command, args []string) error {
\tfmt.Println("V1 called")
\treturn nil
}/<code>

在Bash中,命令行操作如下:

<code>$: go run main.go foo bar v1
V1 called/<code>

當然,現實中我也是這麼做的。具體工具包的實現,請參考: x-mod/cmd。有了這樣一個程序友好的命令行工具包,下一步就是寫一個項目框架的快速啟動工具,將這個包用進去了。


分享到:


相關文章: