Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Cobra to create CLI Application in Golang

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article focuses on "how to use Cobra in Golang to create CLI applications", interested friends may wish to take a look. The method introduced in this paper is simple, fast and practical. Let's let the editor take you to learn how to use Cobra to create CLI applications in Golang.

For developers, you may need to use many CLI tools, such as npm, node, go, python, docker, kubectl, etc., because these tools are very small, have no dependencies, are very suitable for system administration, or some automation tasks, and so on.

Here we choose to use the very famous Cobra library in Golang to develop CLI tools. Cobra is a powerful modern CLI application library. There are many well-known Go projects built using Cobra, such as Kubernetes, Docker, Hugo and so on.

Concept

Cobra is built on top of commands, parameters, and identifiers:

Commands means to perform an action

Args is the execution parameter

Flags is the identifier of these actions

The basic execution command is as follows:

$APPNAME Command Args-Flags# or $APPNAME Command-Flags Args

For example, some of the command-line tools we usually use:

Git clone URL-barego get-u URLnpm install package-savekubectl get pods-n kube-system-l app=cobra example

Let's take a look at the use of Cobra. Here we use the version of go1.13.3 that uses Go Modules for package management. If you are not familiar with this part of the knowledge, you can check out our previous article on the basic use of Go Modules (video).

Create a new directory named my-calc as the project directory, and then initialize modules:

$mkdir my-calc & & cd my-calc# if go modules is not enabled by default, you need to execute export GO111MODULE=on to enable $go mod init my-calcgo: creating new go.mod: module my-calc

After initialization, you can see that there is an additional go.mod file under the root directory of the project. Now that we have not installed the cobra library, execute the following command to install it:

# it is highly recommended to configure this environment variable $export GOPROXY= https://goproxy.cn$ go get-u github.com/spf13/cobra/cobra

After the installation is successful, we can now use the cobra init command to initialize the scaffolding of the CLI application:

$cobra init-pkg-name my-calcYour Cobra applicaton is ready at/Users/ych/devs/workspace/youdianzhishi/course/my-calc

It is important to note that the new version of the cobra library needs to provide a-- pkg-name parameter for initialization, that is, specify the name of the module we initialized above. The above init command creates a basic CLI application project:

$tree.. ├── LICENSE ├── cmd │ └── root.go ├── go.mod ├── go.sum └── main.go1 directory, 5 files

Main.go is the entry point of CLI application, and the Execute function under cmd/root.go is called in main.go:

/ / main.gopackage mainimport "my-calc/cmd" func main () {cmd.Execute ()}

Then let's take a look at the cmd/root.go file.

RootCmd

The root (root) command is the most basic command of the CLI tool. For example, for the go get URL we used earlier, go is the root command, and get is the subcommand of the root command go. In root.go, the cobra command is directly used to initialize the rootCmd structure, and all other commands in CLI will be subcommands of the root command rootCmd.

Here we remove the comments inside the rootCmd variable in cmd/root.go and add a fmt.Println ("Hello Cobra CLI") to the Run function:

Var rootCmd = & cobra.Command {Use: "my-calc", Short: "A brief description of your application", Long: `A longer description that spans multiple lines and likely containsexamples 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 filesto quickly create a Cobra application. `, Run: func (cmd * cobra.Command, args [] string) {fmt.Println ("Hello Cobra CLI")},}

At this point, we execute the following command under the project root directory to build:

$go build-o my-calc

This command generates a binary file called my-calc in the root directory of the project. If you execute this binary file directly, you can see the output shown below:

$. / my-calc

Hello Cobra CLI

Init

We know that the init function is the first function to be called when initializing the package in Golang. In cmd/root.go, we can see that cobra.OnInitialize (initConfig) is called in the init function, that is, whenever a command is executed or called, it executes all the functions in the init function before executing the execute method. This initialization can be used to load configuration files, constructors, and so on, depending on the actual situation of our application.

In the initialization function, cobra.OnInitialize (initConfig) calls the initConfig function, so when the rootCmd execution method RUN: func runs, the rootCmd root command will first run the initConfig function, and when all the initialization functions are completed, the rootCmd RUN: func execution function will be executed.

We can add some Debug information to the initConfig function:

Func initConfig () {fmt.Println ("I'm inside initConfig function in cmd/root.go")...}

Then rebuild it again and execute it again:

$go build-o my-calc$. / my-calcI'm inside initConfig function in cmd/root.goHello Cobra CLI

You can see that the information in the initConfig function is run first, and then the contents of the function are actually executed.

In order to understand the whole process of CLI execution, we also add some Debug information to main.go:

/ / cmd/root.gofunc init () {fmt.Println ("I'm inside init function in cmd/root.go") cobra.OnInitialize (initConfig).} func initConfig () {fmt.Println ("I'm inside initConfig function in cmd/root.go").} / / main.gofunc main () {fmt.Println ("I'm inside main function in main.go") cmd.Execute ()}

Then rebuild it again and execute it again:

$go build-o my-calc$. / my-calcI'm inside init function in cmd/root.goI'm inside main function in main.goI'm inside initConfig function in cmd/root.goHello Cobra CLI

Based on the log information above, we can understand the flow of the CLI command.

The last thing the init function deals with is flags. Flags is similar to the identifier of a command. We can think of them as some kind of conditional operation, providing two types of identifiers in Cobra: Persistent Flags and Local Flags.

Persistent Flags: this flag can be used for the command assigned to it and all subcommands of that command.

Local Flags: this flag can only be used for commands assigned to it.

InitConfig

This function is mainly used to set a configuration file called .my-calc under the home directory, which will be used if it exists.

/ / cmd/root.go// initConfig reads the configuration file and environment variable func initConfig () {if cfgFile! = "" {/ / use the configuration file passed in the flag flag viper.SetConfigFile (cfgFile)} else {/ / to get the Home directory home Err: = homedir.Dir () if err! = nil {fmt.Println (err) os.Exit (1)} / / find the configuration file viper.AddConfigPath (home) named ".my-calc" under the Home directory. Viper.SetConfigName (".my-calc")} / / read the matching environment variable viper.AutomaticEnv () / / if there is a configuration file Then read it if err: = viper.ReadInConfig () Err = = nil {fmt.Println ("Using config file:", viper.ConfigFileUsed ())}}

Viper is a very good Golang library for solving configuration files. It can read information from JSON, TOML, YAML, HCL, envfile and Java properties configuration files. It is very powerful, and it is not just simple to read configuration. For more information, please see the introduction to Git Warehouse: https://github.com/spf13/viper.

Now that we can remove some of the print statements we added earlier, we have created a my-calc command as a rootCmd command. Executing the root command will print the Hello Cobra CLI information, and then add some other commands for our CLI application.

Add data

Create a command called add under the root directory of the project, and Cobra adds a new command by: cobra add, so we will do this directly here:

$cobra add addadd created at / Users/ych/devs/workspace/youdianzhishi/course/my-calc$ tree.. ├── LICENSE ├── cmd │ ├── add.go │ └── root.go ├── go.mod ├── go.sum main.go └── my-calc1 directory, 7 files

Now we can see that a new add.go file has been added to the cmd/root.go file, and we can see that this file is similar to cmd/root.go. First, you declare a structure variable named addCmd, which is of type * cobra.Command pointer, and * cobra.Command has a RUN function with a * cobra.Command pointer and a string slicing parameter.

Then initialize it in the init function, and after initialization, add it to the rootCmd root command rootCmd.AddCommand (addCmd), so we can think of addCmd as a subcommand of rootCmd.

Also now rebuild the application and then execute:

$go build-o my-calc$. / my-calcHello Cobra CLI$. / my-calc addadd called

You can see that the add command can run normally. Next, let's let the change command support adding some numbers. We know that the user string slice is used as a parameter in the RUN function, so to support adding numbers, we first need to convert the string to int type and return the calculation result. Add a function named intAdd to the cmd/add.go file with the following definition:

/ / cmd/add.gofunc intAdd (args [] string) {var sum int / / Loop args parameter, the first value of the loop is the index of args, here we do not need So use _ to ignore for _, ival: = range args {/ / convert string to int type temp Err: = strconv.Atoi (ival) if err! = nil {panic (err)} sum = sum + temp} fmt.Printf ("Addition of numbers% s is% d\ n", args, sum)}

Then in the addCmd variable, update the RUN function, remove the default print information, and call the addInt function declared above:

/ / addCmdRun: func (cmd * cobra.Command, args [] string) {intAdd (args)}

Then rebuild the application and execute the command as follows:

$go build-o my-calc$. / my-calcHello Cobra CLI# notice the spaces between parameters $. / my-calc add 1 2 3Addition of numbers [1 2 3] is 6

Since the args parameter in the RUN function is a string slice, we can pass any number of parameters, but there is a drawback that we can only calculate integers, not decimals. For example, if we perform the following calculation, we will directly panic:

$. / my-calc add 12 3.5panic: strconv.Atoi: parsing "3.5": invalid syntaxgoroutine 1 [running]: my-calc/cmd.intAdd (0xc0000a5890, 0x3, 0x3).

Because in the intAdd function, we just convert the string to int, not the float32/64 type, we can add a flag identifier to the addCmd command to help CLI determine whether it is an int calculation or a float calculation.

Inside the init function of the cmd/add.go file, we create a local identifier of type Bool, named float, abbreviated to f, and the default value is false. This default value is very important, meaning that even if the flag identifier is not called on the command line, the value of the identifier will be false.

/ / cmd/add.gofunc init () {rootCmd.AddCommand (addCmd) addCmd.Flags () .BoolP ("float", "f", false, "Add Floating Numbers")}

Then create a function of floatAdd:

Func floatAdd (args [] string) {var sum float64 for _, fval: = range args {/ / convert the string to float64 type temp, err: = strconv.ParseFloat (fval 64) if err! = nil {panic (err)} sum = sum + temp} fmt.Printf ("Sum of floating numbers% s is% f\ n", args, sum)}

This function is almost the same as the intAdd function above, except that it converts strings to float64 types. Then in the RUN function of addCmd, we determine whether to call intAdd or floatAdd based on the identifier passed in, and if the-- float or-f flag is passed, the floatAdd function will be called.

/ / cmd/add.go// addCmdRun: func (cmd * cobra.Command, args [] string) {/ / get the value of the float identifier. Default is false fstatus, _: = cmd.Flags () .GetBool ("float") if fstatus {/ / if it is true, call floatAdd function floatAdd (args)} else {intAdd (args)}}

Now recompile and build the CLI application as follows:

$go build-o my-calc$. / my-calc add 12 3Addition of numbers [123] is 6 $. / my-calc add 123.5-fSum of floating numbers [123.5] is 6.500000 $. / my-calc add 123.5-- floatSum of floating numbers [123.5] is 6.500000

Then we will add some subcommands to addCmd to extend it.

Add an even number

Also from the project root, execute the following command to add a command named even:

$cobra add eveneven created at / Users/ych/devs/workspace/youdianzhishi/course/my-calc

As above, we will add a file named even.go under the root directory, modify the init function in this file, and change rootCmd to addCmd, because we are adding subcommands for addCmd:

/ / cmd/even.gofunc init () {addCmd.AddCommand (evenCmd)}

Then update the RUN function of the evenCmd structure parameter:

/ / cmd/even.goRun: func (cmd * cobra.Command, args [] string) {var evenSum int for _, ival: = range args {temp, _: = strconv.Atoi (ival) if temp%2 = = 0 {evenSum = evenSum + temp}} fmt.Printf ("The even addition of% s is% d\ n", args, evenSum)}

First convert the string to an integer, and then determine if it is an even number before accumulating. Then recompile and build the application:

$go build-o my-calc$. / my-calc add even 12 3 4 5 6The even addition of [12 3 4 5 6] is 12

My-calc is our root command, add is a subcommand of rootCmd, and even is a subcommand of addCmd, so call it as above. You can add an odd subcommand in the same way.

At this point, I believe you have a deeper understanding of "how to use Cobra to create CLI applications in Golang". You might as well do it in practice. Here is the website, more related content can enter the relevant channels to inquire, follow us, continue to learn!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report