為什麼使用命令列
大型項目中少不了資料升級,如果採用web服務,一來不夠安全,二來資料量大的時候也會出逾時的情況。這時使用命令列是比較合適的方式了。
命令列中的MVC
web項目一般採用MVC模式,對於命令列有嗎?
對於命令列則有command(命令)和flag(參數),golang內建了flag包,不過功能不夠強大,這裡我們使用第三方包cobra
cobra 的使用
具體用法可以參考官方文檔,我就不細說了。
妙用
按照官方的結構,不好實現自動註冊,每次增加新的命令或檔案夾不好管理,需要改動代碼。經過一番思考,發現可以利用golang的init機制來達到我的目的。
目錄結構如下:
運行效果
其中rootCmd.go 中初始化根命令rootCmd
,同時封裝兩個函數,一個是添加子命令的,一個是執行的。
package rootcmdimport ( "fmt" "github.com/spf13/cobra")var rootCmd = &cobra.Command{ Use: "cli", Run: func(cmd *cobra.Command, args []string) { fmt.Println("OK") },}//封裝了兩個函數func AddCommand(cmd *cobra.Command) { rootCmd.AddCommand(cmd)}func Execute() error { return rootCmd.Execute()}
對於子命令,我可以匯入rootcmd所在的包,然後在init函數裡,調用rootcmd.AddCommand
比如updateCmd.go
package updateimport ( "github.com/spf13/cobra" "fmt" "github.com/dwdcth/cli_sample/rootcmd")// 註冊命令func init() { rootcmd.AddCommand(userCmd)}var userCmd = &cobra.Command{ Short: "user", Use: "user ", Run: func(cmd *cobra.Command, args []string) { fmt.Println("run user update command") },}
對於main包,使用"_",匯入子命令檔案夾,和rootcmd,並調用 rootcmd.Execute()即可。
這樣添加新的命令不增加新的package時,就不需要更改cli.go,實現了自動註冊的目的。
package mainimport ( "fmt" "os" "github.com/dwdcth/cli_sample/rootcmd" _"github.com/dwdcth/cli_sample/task" _"github.com/dwdcth/cli_sample/update")func main() { if err := rootcmd.Execute(); err != nil { fmt.Println(err) os.Exit(1) }}
完整的代碼在此