Cobra 命令行

因为之前写 Django,python manage.py这个命令非常好用,想看看能不能实现类似的效果。搜索之后发现了更强的cobra,看简介中使用的项目就知道非常不错。代码组织参考的frp的。

PATH/frp/cmd,frpc和fprs分别是客户端和服务端

├───frpc
│   │   main.go
│   │
│   └───sub
│           http.go
│           https.go
│           reload.go
│           root.go
│           status.go
│           stcp.go
│           sudp.go
│           tcp.go
│           tcpmux.go
│           udp.go
│           xtcp.go
│
└───frps
        main.go
        root.go

添加

go get -u github.com/spf13/cobra/cobra

在项目目录中执行,appname mycli,其中cmd中 rootCmd 的名称是mycli,这里建议和appname一样,后面可以直接go install之后使用mycli即可。

mkdir cmd && cd cmd
cobra init mycli --pkg-name mycli

cmd
└───mycli
    │   LICENSE
    │   main.go
    │
    └───cmd
            root.go

模板代码 import错误,重新按照自己项目的组织方式重写 import即可。

package main

import "mycli/cmd"

func main() {
	cmd.Execute()
}

测试使用:

go run main.go

测试完后,可以go install到系统的路径里,然后使用即可,单个二进制文件发布也非常方便。

嵌套命令行

mycli CMD SUBCMD

增加第一级命令

> cobra add user

> go run . user
user called

增加user下的其他指令

> cobra add userAdd --parent userCmd
> go run . user userAdd
userAdd called

现在代码的结构

mycli
│   LICENSE
│   main.go
│
└───cmd
        root.go
        user.go
        userAdd.go

每一次cobra add都会生成一个文件,--parent指定命令属于哪一个,默认是添加到rootCmd

  • 可以将cobra生成的文件自己重构,移动到对应文件中
  • userAdd这个是文件名,也是命令名,在cmd的Use属性中可以修改为add,这样使用时mycli user add [flags]

结合到已有系统中

以web server为例,都会设计一个NewServer方法,然后封装一个执行方法,以命令为入口执行即可:

mycli server
// serverCmd represents the server command
var serverCmd = &cobra.Command{
	Use:   "server",
	Short: "A brief description of your command",
	Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
	Run: func(cmd *cobra.Command, args []string) {
		runServer()
		fmt.Println("server called")
	},
}

func init() {
	rootCmd.AddCommand(serverCmd)

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// serverCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// serverCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

func runServer() {
	e := server.NewServer()
	e.Logger.Fatal(e.Start(config.Config.Port))
}