Go語(yǔ)言命令行參數(shù)及cobra使用方法
1.原生命令行參數(shù)
os 包以跨平臺(tái)的方式,提供了一些與操作系統(tǒng)交互的函數(shù)和變量。程序的命令行參數(shù)可從 os 包的 Args 變量獲??;os 包外部使用 os.Args
訪問(wèn)該變量
os.Args
變量是一個(gè)字符串(string)的 切片(slice),os.Args
的第一個(gè)元素:os.Args[0]
,是命令本身的名字;其它的元素則是程序啟動(dòng)時(shí)傳給它的參數(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í)行程序,會(huì)輸出所有參數(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)用簡(jiǎn)短描述 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 配置庫(kù)中的相應(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 { // 如果沒(méi)有指定配置文件路徑,就根據(jù)用戶的主目錄動(dòng)態(tài)生成配置文件路徑 home, err := os.UserHomeDir() cobra.CheckErr(err) viper.AddConfigPath(home) viper.SetConfigType("yaml") viper.SetConfigName(".cobra") } // 用于自動(dòng)讀取環(huán)境變量 viper.AutomaticEnv() // 用于讀取配置文件。如果成功讀取,則輸出使用的配置文件路徑 if err := viper.ReadInConfig(); err == nil { fmt.Println("Using config file:", viper.ConfigFileUsed()) } }
創(chuàng)建你的 main.go
main.go 文件通常非常裸露。它有一個(gè)目的:初始化 Cobra:
package go_test import "go-test/cmd" func main() { err := cmd.Execute() if err != nil { return } }
創(chuàng)建其他命令
可以定義其他命令,并且通常每個(gè)命令都有自己的文件 在 cmd/ 目錄中。
例如:如果要?jiǎng)?chuàng)建版本命令,則需要?jiǎ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í)行時(shí)的具體操作 // 在本例中,當(dāng)執(zhí)行 version 命令時(shí),會(huì)打印出 “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
時(shí),將會(huì)觸發(fā) versionCmd 命令的執(zhí)行,打印出應(yīng)用程序的版本信息
子命令
命令可能具有子命令,而子命令又可能具有其他子命令
請(qǐng)考慮以下目錄結(jié)構(gòu):AddCommand
├── cmd │ ├── root.go │ └── sub1 │ ├── sub1.go │ └── sub2 │ ├── leafA.go │ ├── leafB.go │ └── sub2.go └── main.go
返回和處理錯(cuò)誤
如果您希望向命令的調(diào)用方返回錯(cuò)誤,可以使用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)志提供修飾符來(lái)控制操作命令的運(yùn)行方式
1、持久性標(biāo)志
標(biāo)志可以是“持久性的”,這意味著此標(biāo)志將可用于它所分配的命令以及該命令下的每個(gè)命令。為全局標(biāo)志,將標(biāo)志指定為根上的持久標(biāo)志
持久性標(biāo)記的定義通常包括全局性的配置參數(shù),例如日志級(jí)別、配置文件路徑、全局選項(xiàng)等
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
2、本地標(biāo)志
在本地分配標(biāo)志,該標(biāo)志僅適用于該特定命令
本地標(biāo)記通常用于定義特定命令所需的選項(xiàng)和參數(shù),例如某個(gè)命令的特定配置選項(xiàng)
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)為手動(dòng)處理命令行標(biāo)志更適合你,也可以不使用 Viper 進(jìn)行綁定
4、參數(shù)必須
默認(rèn)情況下,標(biāo)志是可選的,如果想設(shè)置某個(gè)參數(shù)是必要的,可以進(jìn)行設(shè)置:
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)") rootCmd.MarkFlagRequired("region")
或者,對(duì)于持久性標(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)記的互斥(也就是不能同時(shí)出現(xiàn)):
rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON") rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML") rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")
如果要要求組中至少有一個(gè)標(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ù)的驗(yàn)證:
內(nèi)置了以下驗(yàn)證器:Args Command
參數(shù)數(shù)量:
- NoArgs- 如果有任何位置參數(shù),則報(bào)告錯(cuò)誤。
- ArbitraryArgs- 接受任意數(shù)量的參數(shù)。
- MinimumNArgs(int)- 如果提供的位置參數(shù)少于 N 個(gè),則報(bào)告錯(cuò)誤。
- MaximumNArgs(int)- 如果提供了超過(guò) N 個(gè)位置參數(shù),則報(bào)告錯(cuò)誤。
- ExactArgs(int)- 如果位置參數(shù)不完全是 N 個(gè),則報(bào)告錯(cuò)誤。
- RangeArgs(min, max)- 如果參數(shù)數(shù)不在min和max之間,則報(bào)告錯(cuò)誤
論據(jù)內(nèi)容:
- OnlyValidArgs- 如果字段中未指定任何位置參數(shù),則報(bào)告錯(cuò)誤
此外,還可以將現(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è)置任何滿足的自定義驗(yàn)證器,例如:
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)行自定義驗(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 庫(kù)中,命令的執(zhí)行過(guò)程被分為多個(gè)階段,并且 Cobra 提供了一些Hooks來(lái)允許開(kāi)發(fā)者在這些階段插入自定義的行為
1、PersistentPreRun
在執(zhí)行任何命令之前調(diào)用 PersistentPreRun
。可以使用這個(gè)鉤子來(lái)進(jìn)行全局的初始化操作或者檢查全局的配置參數(shù)
2、PreRun
在執(zhí)行該命令之前調(diào)用 PreRun
。可以使用這個(gè)鉤子來(lái)執(zhí)行一些與特定命令相關(guān)的操作或配置檢查
3、Run
當(dāng)命令被執(zhí)行時(shí),會(huì)調(diào)用 Run
函數(shù)來(lái)執(zhí)行實(shí)際的命令操作
4、PostRun
在執(zhí)行完該命令之后調(diào)用 PostRun
。可以使用這個(gè)鉤子來(lái)執(zhí)行一些與特定命令相關(guān)的清理工作或后處理操作
5、PersistentPostRun
在執(zhí)行完任何命令之后調(diào)用 PersistentPostRun
??梢允褂眠@個(gè)鉤子來(lái)進(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語(yǔ)言命令行參數(shù)及cobra使用方法的文章就介紹到這了,更多相關(guān)Go語(yǔ)言命令行參數(shù)及cobra內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
go內(nèi)存緩存BigCache之Entry封裝源碼閱讀
這篇文章主要介紹了go內(nèi)存緩存BigCache之Entry封裝源碼閱讀2023-09-09golang編程開(kāi)發(fā)使用sort排序示例詳解
這篇文章主要為大家介紹了go語(yǔ)言編程開(kāi)發(fā)使用sort來(lái)排序示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪2021-11-11golang讀取yaml配置文件的方法實(shí)現(xiàn)
本文主要介紹了golang讀取yaml配置文件的方法實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2024-10-10使用gorm.Scopes函數(shù)實(shí)現(xiàn)復(fù)用查詢邏輯示例
這篇文章主要為大家介紹了使用gorm.Scopes函數(shù)實(shí)現(xiàn)復(fù)用查詢邏輯示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換
在軟件開(kāi)發(fā)的世界里,數(shù)據(jù)類型轉(zhuǎn)換是一項(xiàng)基礎(chǔ)而重要的技能,尤其在Go語(yǔ)言這樣類型嚴(yán)格的語(yǔ)言中,正確高效地進(jìn)行類型轉(zhuǎn)換對(duì)于性能優(yōu)化和代碼質(zhì)量至關(guān)重要,本文給大家介紹了Go實(shí)現(xiàn)字符串與數(shù)字的高效轉(zhuǎn)換,需要的朋友可以參考下2024-02-02