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))
}