Go語言命令行參數(shù)及cobra使用方法
1.原生命令行參數(shù)
os 包以跨平臺的方式,提供了一些與操作系統(tǒng)交互的函數(shù)和變量。程序的命令行參數(shù)可從 os 包的 Args 變量獲取;os 包外部使用 os.Args 訪問該變量
os.Args 變量是一個字符串(string)的 切片(slice),os.Args 的第一個元素:os.Args[0],是命令本身的名字;其它的元素則是程序啟動時傳給它的參數(shù)
func main() {
var s, sep string
for i := 1; i < len(os.Args); i++ {
s += sep + os.Args[i]
sep = " "
}
fmt.Println(s)
}
執(zhí)行程序,會輸出所有參數(shù),以空格做分割:
go run hello.go 1 2.1 nma

2.使用CIL框架Cobra
Cobra 應(yīng)用程序?qū)⒆裱韵陆M織結(jié)構(gòu):
? appName/
? cmd/
add.go
your.go
commands.go
here.go
main.go
創(chuàng)建 rootCmd
Cobra 不需要任何特殊的構(gòu)造函數(shù)。只需創(chuàng)建命令即可
package cmd
import (
"fmt"
"os"
"github.com/spf13/cobra"
"github.com/spf13/viper"
)
var (
cfgFile string // 配置文件路徑
userLicense string // 許可證類型
rootCmd = &cobra.Command{
// 應(yīng)用名稱
Use: "cobra-cli",
// 應(yīng)用簡短描述
Short: "A generator for Cobra based Applications",
// 應(yīng)用詳細(xì)描述
Long: `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.`,
}
)
// Execute 用于執(zhí)行根命令 rootCmd
func Execute() error {
return rootCmd.Execute()
}
func init() {
// 在執(zhí)行任何子命令之前調(diào)用 initConfig() 函數(shù)
cobra.OnInitialize(initConfig)
// 配置文件
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
// 作者信息
rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
// 許可證信息
rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
// 使用Viper進(jìn)行配置
rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
// 將命令行標(biāo)志綁定到 Viper 配置庫中的相應(yīng)參數(shù)
err := viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
if err != nil {
return
}
err2 := viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
if err2 != nil {
return
}
// 設(shè)置默認(rèn)配置值
viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
viper.SetDefault("license", "apache")
// 用于添加子命令
rootCmd.AddCommand(addCmd)
rootCmd.AddCommand(initCmd)
}
// 初始化應(yīng)用程序的配置
func initConfig() {
// 判斷是否指定了配置文件路徑,如果指定了,則將其設(shè)置為 Viper 配置文件
if cfgFile != "" {
viper.SetConfigFile(cfgFile)
} else {
// 如果沒有指定配置文件路徑,就根據(jù)用戶的主目錄動態(tài)生成配置文件路徑
home, err := os.UserHomeDir()
cobra.CheckErr(err)
viper.AddConfigPath(home)
viper.SetConfigType("yaml")
viper.SetConfigName(".cobra")
}
// 用于自動讀取環(huán)境變量
viper.AutomaticEnv()
// 用于讀取配置文件。如果成功讀取,則輸出使用的配置文件路徑
if err := viper.ReadInConfig(); err == nil {
fmt.Println("Using config file:", viper.ConfigFileUsed())
}
}
創(chuàng)建你的 main.go
main.go 文件通常非常裸露。它有一個目的:初始化 Cobra:
package go_test
import "go-test/cmd"
func main() {
err := cmd.Execute()
if err != nil {
return
}
}
創(chuàng)建其他命令
可以定義其他命令,并且通常每個命令都有自己的文件 在 cmd/ 目錄中。
例如:如果要創(chuàng)建版本命令,則需要創(chuàng)建 cmd/version.go 和 使用以下內(nèi)容填充它:
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
// 將 versionCmd 命令添加到根命令 rootCmd 中
func init() {
rootCmd.AddCommand(versionCmd)
}
var versionCmd = &cobra.Command{
Use: "version",
Short: "Print the version number of Hugo",
Long: `All software has versions. This is Hugo's`,
// 用于定義命令被執(zhí)行時的具體操作
// 在本例中,當(dāng)執(zhí)行 version 命令時,會打印出 “Hugo Static Site Generator v0.9 – HEAD” 版本信息
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
},
}
結(jié)合上面的代碼,當(dāng)用戶輸入 cobra-cli version 時,將會觸發(fā) versionCmd 命令的執(zhí)行,打印出應(yīng)用程序的版本信息
子命令
命令可能具有子命令,而子命令又可能具有其他子命令
請考慮以下目錄結(jié)構(gòu):AddCommand
├── cmd │ ├── root.go │ └── sub1 │ ├── sub1.go │ └── sub2 │ ├── leafA.go │ ├── leafB.go │ └── sub2.go └── main.go
返回和處理錯誤
如果您希望向命令的調(diào)用方返回錯誤,可以使用RunE
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
func init() {
rootCmd.AddCommand(tryCmd)
}
var tryCmd = &cobra.Command{
Use: "try",
Short: "Try and possibly fail at something",
RunE: func(cmd *cobra.Command, args []string) error {
if err := someFunc(); err != nil {
return err
}
return nil
},
}
3.cobra使用標(biāo)志
標(biāo)志提供修飾符來控制操作命令的運(yùn)行方式
1、持久性標(biāo)志
標(biāo)志可以是“持久性的”,這意味著此標(biāo)志將可用于它所分配的命令以及該命令下的每個命令。為全局標(biāo)志,將標(biāo)志指定為根上的持久標(biāo)志
持久性標(biāo)記的定義通常包括全局性的配置參數(shù),例如日志級別、配置文件路徑、全局選項等
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
2、本地標(biāo)志
在本地分配標(biāo)志,該標(biāo)志僅適用于該特定命令
本地標(biāo)記通常用于定義特定命令所需的選項和參數(shù),例如某個命令的特定配置選項
localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
3、使用 Config 綁定標(biāo)志
可以使用 viper 綁定您的標(biāo)志:
var author string
func init() {
rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}
使用 Viper 綁定命令行標(biāo)志可使配置管理更加一致、靈活和可組合。然而,具體是否需要綁定命令行標(biāo)志取決于你的應(yīng)用程序需求和偏好,如果你認(rèn)為手動處理命令行標(biāo)志更適合你,也可以不使用 Viper 進(jìn)行綁定
4、參數(shù)必須
默認(rèn)情況下,標(biāo)志是可選的,如果想設(shè)置某個參數(shù)是必要的,可以進(jìn)行設(shè)置:
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")
或者,對于持久性標(biāo)志:
rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkPersistentFlagRequired("region")
5、標(biāo)記Groups
如果您有不同的標(biāo)志必須一起提供(例如,如果他們提供標(biāo)志,他們也必須提供標(biāo)志),也可以強(qiáng)制進(jìn)行設(shè)定:
rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
rootCmd.MarkFlagsRequiredTogether("username", "password")
還可以設(shè)置不同標(biāo)記的互斥(也就是不能同時出現(xiàn)):
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
如果要要求組中至少有一個標(biāo)志存在,也可以指定:
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
rootCmd.MarkFlagsOneRequired("json", "yaml")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
4.Cobra位置參數(shù)和自定義參數(shù)
可以指定位置參數(shù)的驗證:
內(nèi)置了以下驗證器:Args Command
參數(shù)數(shù)量:
- NoArgs- 如果有任何位置參數(shù),則報告錯誤。
- ArbitraryArgs- 接受任意數(shù)量的參數(shù)。
- MinimumNArgs(int)- 如果提供的位置參數(shù)少于 N 個,則報告錯誤。
- MaximumNArgs(int)- 如果提供了超過 N 個位置參數(shù),則報告錯誤。
- ExactArgs(int)- 如果位置參數(shù)不完全是 N 個,則報告錯誤。
- RangeArgs(min, max)- 如果參數(shù)數(shù)不在min和max之間,則報告錯誤
論據(jù)內(nèi)容:
- OnlyValidArgs- 如果字段中未指定任何位置參數(shù),則報告錯誤
此外,還可以將現(xiàn)有檢查與任意其他檢查相結(jié)合,例如:
var cmd = &cobra.Command{
Short: "hello",
Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello, World!")
},
}
可以設(shè)置任何滿足的自定義驗證器,例如:
var cmd = &cobra.Command{
Short: "hello",
Args: func(cmd *cobra.Command, args []string) error {
if err := cobra.MinimumNArgs(1)(cmd, args); err != nil {
return err
}
// 運(yùn)行自定義驗證邏輯
if myapp.IsValidColor(args[0]) {
return nil
}
return fmt.Errorf("invalid color specified: %s", args[0])
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello, World!")
},
}
5.Cobra PreRun和PostRun鉤子
在 Cobra 庫中,命令的執(zhí)行過程被分為多個階段,并且 Cobra 提供了一些Hooks來允許開發(fā)者在這些階段插入自定義的行為
1、PersistentPreRun
在執(zhí)行任何命令之前調(diào)用 PersistentPreRun。可以使用這個鉤子來進(jìn)行全局的初始化操作或者檢查全局的配置參數(shù)
2、PreRun
在執(zhí)行該命令之前調(diào)用 PreRun??梢允褂眠@個鉤子來執(zhí)行一些與特定命令相關(guān)的操作或配置檢查
3、Run
當(dāng)命令被執(zhí)行時,會調(diào)用 Run 函數(shù)來執(zhí)行實際的命令操作
4、PostRun
在執(zhí)行完該命令之后調(diào)用 PostRun??梢允褂眠@個鉤子來執(zhí)行一些與特定命令相關(guān)的清理工作或后處理操作
5、PersistentPostRun
在執(zhí)行完任何命令之后調(diào)用 PersistentPostRun??梢允褂眠@個鉤子來進(jìn)行全局的清理工作或輸出全局概要信息
例如:
package main
import (
"fmt"
"github.com/spf13/cobra"
)
func main() {
var rootCmd = &cobra.Command{
Use: "root [sub]",
Short: "My root command",
PersistentPreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
},
PreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd Run with args: %v\n", args)
},
PostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
},
}
var subCmd = &cobra.Command{
Use: "sub [no options!]",
Short: "My subcommand",
PreRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
},
Run: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd Run with args: %v\n", args)
},
PostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
},
PersistentPostRun: func(cmd *cobra.Command, args []string) {
fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
},
}
rootCmd.AddCommand(subCmd)
rootCmd.SetArgs([]string{""})
rootCmd.Execute()
fmt.Println()
rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
rootCmd.Execute()
}
輸出:
Inside rootCmd PersistentPreRun with args: []
Inside rootCmd PreRun with args: []
Inside rootCmd Run with args: []
Inside rootCmd PostRun with args: []
Inside rootCmd PersistentPostRun with args: []Inside rootCmd PersistentPreRun with args: [arg1 arg2]
Inside subCmd PreRun with args: [arg1 arg2]
Inside subCmd Run with args: [arg1 arg2]
Inside subCmd PostRun with args: [arg1 arg2]
Inside subCmd PersistentPostRun with args: [arg1 arg2]
到此這篇關(guān)于Go語言命令行參數(shù)及cobra使用方法的文章就介紹到這了,更多相關(guān)Go語言命令行參數(shù)及cobra內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Skywalking-go自動監(jiān)控增強(qiáng)使用探究
這篇文章主要介紹了Skywalking-go自動監(jiān)控增強(qiáng)使用深入探究,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01
Go語言同步與異步執(zhí)行多個任務(wù)封裝詳解(Runner和RunnerAsync)
這篇文章主要給大家介紹了關(guān)于Go語言同步與異步執(zhí)行多個任務(wù)封裝(Runner和RunnerAsync)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01

