今天要介紹一款開源軟體 — Cobra Command
source :https://github.com/spf13/cobra
Cobra是用GOlang來編寫的,當然我們建立也是用go去寫,他的功能主要是來幫助我們建立屬於自己的command,以往我們再建立屬於我們自己的command往往都非常煩雜,從command到parse參數等,以及收到參數要怎樣執行,相信有寫過的朋友就知道除了要考慮到很多面向之外可能還藏有許多的bug,而cobra就是來幫助大家省時間的,他除了內建許多功能之外,有關command加參數等的工作他也都會幫助您,可說是非常強大的開發工具
筆者會簡單介紹他的功能,讓大家上手好發揮
首先我們先下載他的package來開發
go get -u github.com/spf13/cobra/cobra
之後我們利用他的binary來建立一個範例檔
```
$ cobra init hello(YourApp)
Your Cobra application is ready at
/home/sam/go/src/hello.Give it a try by going there and running `go run main.go`.
Add commands to it by running `cobra add [cmdname]`.
這樣就建立好了,接著我們看一下這個結構
$ tree hello/
hello/
├── cmd
│ └── root.go
├── LICENSE
└── main.go1 directory, 3 files
我們會從main開始,而root.go就是我們寫我們APP用的,當然你也可以自己建立其他檔案去include,但我們簡單說明就先不這麼做了
我們先看main.go
// Copyright © 2017 NAME HERE <EMAIL ADDRESS>
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.package mainimport “hello/cmd”func main() {
cmd.Execute()
}
他會去執行再cmd/root.go裡的Execute這個function,我們接著往下看
cmd/root.go
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
// Licensed under the Apache License, Version 2.0 (the “License”);
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an “AS IS” BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.package cmdimport (
“fmt”
“os”homedir “github.com/mitchellh/go-homedir”
“github.com/spf13/cobra”
“github.com/spf13/viper”
)var cfgFile string// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
Use: “hello”,
Short: “A brief description of your application”,
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. 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.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
if err := RootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}func init() {
cobra.OnInitialize(initConfig)// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
RootCmd.PersistentFlags().StringVar(&cfgFile, “config”, “”, “config file (default is $HOME/.hello.yaml)”)// Cobra also supports local flags, which will only run
// when this action is called directly.
RootCmd.Flags().BoolP(“toggle”, “t”, false, “Help message for toggle”)
}// initConfig reads in config file and ENV variables if set.
func initConfig() {
if cfgFile != “” {
// Use config file from the flag.
viper.SetConfigFile(cfgFile)
} else {
// Find home directory.
home, err := homedir.Dir()
if err != nil {
fmt.Println(err)
os.Exit(1)
}// Search config in home directory with name “.hello” (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(“.hello”)
}viper.AutomaticEnv() // read in environment variables that match// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
fmt.Println(“Using config file:”, viper.ConfigFileUsed())
}
}
這邊看起來很多很雜,不過我們先從最上面定義RootCmd來看,這邊可以看到他會回傳一個struct的address給Rootaddress,而這個struct Command蠻重要的,他主要就是這個command結構去做很多事,但這結構定義很多東西,沒關係我們先看到範例的就夠用了
var RootCmd = &cobra.Command{
Use: “hello”,
Short: “A brief description of your application”,
Long: `A longer description that spans multiple lines and likely contains
examples and usage of using your application. 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.`,
// Uncomment the following line if your bare application
// has an action associated with it:
// Run: func(cmd *cobra.Command, args []string) { },
}
,可以看到有short,long,主要上是用來像大家說明這個command的用途,當然你也可以空白,這邊由你決定
而下面可以看到被註解掉的Run,這個則是要run的func,如果你不想別人直接輸入rootcmd有任何用途我們就會註解掉,但在這邊我們先來個簡單hello world就好,不懂的朋友可以先試試看之後就會明白了
改成下方
var RootCmd = &cobra.Command{
Use: “hello”,
Short: “Short Hello World”,
Long:”Long Hello World” ,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
fmt.Println(“Hello World”)
},
}
Run裏面我們就讓他執行印出hello world就好了
好一個簡單的command就完成了,我們可以用go build 去編譯這個binary
$ go build -o hello main.go
這樣我們就完成了我們的binary
可以試試
$ ./hello
Hello World
$ ./hello -h
Long Hello WorldUsage:
hello [flags]Flags:
— config string config file (default is $HOME/.hello.yaml)
-h, — help help for hello
-t, — toggle Help message for toggle
還可以看到他內建的help功能,就會看到上方我們定義的long囉,完成囉!
如果很沒感覺先別及我們繼續往下看
加入一些參數,來豐富一下我們的command功能
var name string
var school string
var RootCmd = &cobra.Command{
Use: “hello”,
Short: “Short Hello World”,
Long:”Long Hello World” ,
// Uncomment the following line if your bare application
// has an action associated with it:
Run: func(cmd *cobra.Command, args []string) {
if len(name)!=0{
fmt.Printf(“MY name is %s, i’m coming from %s”,name,school)
}
fmt.Println(“Hello World”)
},
}
我們多加了兩個值name與school
但command還不知道我們需要多家兩個參數,所以我們再往下找到func init
func init() {
cobra.OnInitialize(initConfig)// Here you will define your flags and configuration settings.
// Cobra supports persistent flags, which, if defined here,
// will be global for your application.
RootCmd.PersistentFlags().StringVar(&cfgFile, “config”, “”, “config file (default is $HOME/.hello.yaml)”)// Cobra also supports local flags, which will only run
// when this action is called directly.
///RootCmd.Flags().BoolP(“toggle”, “t”, false, “Help message for toggle”)
RootCmd.Flags().StringVarP(&name, “name”, “n”, “”, “your name”)
RootCmd.Flags().StringVarP(&school, “school”, “s”, “”, “your school”)}
我們可以加上後面兩行來建立我們再下command時要的參數,之後一樣我們build起來會發現
./hello -h
Long Hello WorldUsage:
hello [flags]Flags:
— config string config file (default is $HOME/.hello.yaml)
-h, — help help for hello
-n, — name string your name
-s, — school string your school
整個介紹也都跟著改了!!再來我們測試
$ ./hello -n sam -s NTCU
my name is sam, i’m coming from NTCU
Hello World
當然還不只這樣,還有一個subcommand的功能,讓我們可以再root command後面接上我們想要的其他commamd
$ cobra add demo
demo created at /home/sam/go/src/hello/cmd/demo.go
裏面的配置就跟上方的root幾乎一樣了,這邊就不再去做一樣的事情了,最後我們可以測試(記得要重新編譯)
$./hello demo
demo called
$./hello demo -h
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.Usage:
hello demo [flags]Flags:
-h, — help help for demoGlobal Flags:
— config string config file (default is $HOME/.hello.yaml)
這樣就完成了我們的subcommand,至於其他詳細還請看官方的文件囉,這邊指引領大家路門
,有錯跟建議都歡迎提醒,謝謝