将cobra下載下傳到 $GOPATH,用指令:
go get -v github.com/spf13/cobra/cobra
然後使用
go install github.com/spf13/cobra/cobra
, 安裝後在
$GOBIN
下出現了cobra 可執行程式。如果你沒有配置
$GOBIN
,那麼可以在
$GOPATH/bin
下找到 cobra的可執行軟體。
cobra程式隻能在GOPATH之下使用,是以首先你需要進入到GOPATH的src目錄之下,在該目錄下,輸入:
cobra init demo
在你的目前目錄下,應該已經生成了一個demo檔案夾:
demo
├── cmd
│ └── root.go
├── LICENSE
└── main.go
上述便是該檔案夾的結構,我們可以進去該檔案夾,運作:
go run main.go
應該會列印如下結果:
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.
至此,我們的cobra項目便已經生成完畢。
如果你并不想運作cobra的可執行指令生成示例代碼,隻想在項目使用其庫代碼,則上面的内容可以忽略。
附 demo 檔案夾的内容:
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 cmd
import (
"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: "demo",
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/.demo.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 ".demo" (without extension).
viper.AddConfigPath(home)
viper.SetConfigName(".demo")
}
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())
}
}
main.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 main
import "demo/cmd"
func main() {
cmd.Execute()
}
添加子指令
實際操作其實cobra都能幫你完成,假設我們現在需要添加一個test參數,在項目檔案夾下指令行輸入:
cobra add test
執行完成後,現在我們的demo結構應該是:
.
├── cmd
│ ├── root.go
│ └── test.go
├── LICENSE
└── main.go
可以看到,在cmd目錄下,已經生成了一個與我們指令同名的go檔案,你也許已經猜測到,與該指令有關的操作也正是在此處實作。現在執行這個子指令:
go run main.go test
指令行将會列印輸出
test called
那麼現在又有一個問題,如果我們想添加子指令下的子指令呢?
現在讓我們打開test.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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// testCmd represents the test command
var testCmd = &cobra.Command{
Use: "test",
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) {
fmt.Println("test called")
},
}
func init() {
rootCmd.AddCommand(testCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// testCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// testCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
你會發現,在init中有一句
rootCmd.AddCommand(testCmd)
這個rootCmd是什麼?打開root.go,你會發現rootCmd其實就是我們的根指令。我相信機智的同學已經猜出來我們添加子指令的子指令的方法了。現在讓我們在cmd目錄下建立testson.go檔案,項目檔案結構為:
.
├── cmd
│ ├── root.go
│ └── test.go
│ └── testson.go
├── LICENSE
└── main.go
把test.go的内容複制進去,并testson.go檔案修改為如下内容:
cmd/testson.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 cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// testCmd represents the test command
var testsonCmd = &cobra.Command{
Use: "testson",
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) {
fmt.Println("testson called")
},
}
func init() {
testCmd.AddCommand(testsonCmd)
// Here you will define your flags and configuration settings.
// Cobra supports Persistent Flags which will work for this command
// and all subcommands, e.g.:
// testCmd.PersistentFlags().String("foo", "", "A help for foo")
// Cobra supports local flags which will only run when this command
// is called directly, e.g.:
// testCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
現在在指令行運作:
go run main.go test testson
當你看到
testson called
,恭喜你,子指令添加成功!否則你應當檢查你的代碼是否有誤。
添加參數
我相信從init函數中的注釋中,你已經得到了足夠多的資訊來自己操作添加flag,但我還是想要啰嗦兩句。首先是persistent參數,當你的參數作為persistent flag存在時,如注釋所言,在其所有的子指令之下該參數都是可見的。而local flag則隻能在該指令調用時執行。可以做一個簡單的測試,在test.go的init函數中,添加如下内容:
testCmd.PersistentFlags().String("foo", "", "A help for foo")
testCmd.Flags().String("foolocal", "", "A help for foo")
現在在指令行
go run main.go test -h
得到如下結果:
$ go run main.go test -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:
demo test [flags]
demo test [command]
Available Commands:
testson A brief description of your command
Flags:
--foo string A help for foo
--foolocal string A help for foo
-h, --help help for test
Global Flags:
--config string config file (default is $HOME/.demo.yaml)
Use "demo test [command] --help" for more information about a command.
接着讓我們再運作
go run main.go test testson -h
$ go run main.go test testson -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:
demo test testson [flags]
Flags:
-h, --help help for testson
Global Flags:
--config string config file (default is $HOME/.demo.yaml)
--foo string A help for foo
可以發現在Gloabal Flags的變化。test作為root的子指令,仍然可以使用root的persistent flag-> config(可以檢視root.go),而testson作為test的子指令,不僅可以使用test的persistent flag-> fool, 也可以使用test父指令的persistent flag。進而我們可以直覺的看出persistent的作用範圍是該指令之後的所有子指令。接下來你可能會問,那flag支援什麼類型參數?答案是,請檢視官方文檔
請注意,cmd.Flags().String()與 cmd.Flags().StringP()是不一樣的。假如我們在test.go的init下增加如下兩行:
testCmd.Flags().String("f", "", "test")
testCmd.Flags().StringP("aaa", "a", "", "test")
前者調用需要如下形式:
go run main.go test --f
後者有如下兩種形式調用:
go run main.go test --aaa
go run main.go test -a
另外可以額外告知你如何使用slice作為參數,如[]string:
testCmd.Flags().StringSliceP("arr","r", nil, "test arr")
調用該參數的方法為:
go run main.go test -r "a,b,c"
請不要鍵入多餘空格(除非确實需要鍵入),也不要使用空格替代逗号作為分割符。
擷取參數值
在知道了如何設定參數後,我們的下一步當然便是需要在運作時擷取該參數的值。現在讓我們把注意力放到test.go的此部分:
var testCmd = &cobra.Command{
Use: "test",
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) {
fmt.Println("test called")
},
}
讓我們把注意力重新放到上面的代碼上。我們也很容易可以猜測到Use,Short,Long三個參數的作用,這裡便不做闡述(你可以參照添加子指令的子指令的部分的輸出)。顯而易見,我們應該在
Run
這裡來擷取參數并執行我們的指令功能。擷取參數其實也并不複雜。以
testCmd.Flags().StringP("aaa", "a", "", "test")
此為例,我們可以在Run函數裡添加:
str := testCmd.Flags().GetString("aaa")
這樣便可以擷取到該參數的值了,其餘類型參數擷取也是同理。如
testCmd.Flags().GetStringSlice("arr")
,規律并不難見。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
微信公衆号: 共鳴圈
歡迎讨論,郵件: 924948$qq.com 請把$改成@
QQ群:263132197
QQ: 924948