Define Cobra library and make an application from it
Build an application without caring about the frontend
Cobra is a CLI framework for Go. It is a powerful library and tool in Golang used to create CLI (Command-Line Interface) applications. Cobra does this by providing tools that automate the process and provide key abstractions that increase developer productivity.
It is used in many Go projects such as Kubernetes, Hugo, and GitHub CLI and much more. This list contains a more extensive list of projects using Cobra.
Why use Cobraโ
Among the many benefits of using Cobra, here are some to consider:
- Easy to create subcommand-based CLIs and use nested subcommands.
- Automatic help generation for commands and flags.
- Increased productivity because of commands such as
cobra init appname
&cobra add cmdname
. - Helpful, intelligent suggestions (app srverโฆ did you mean app server?).
The Pattern ๐
Cobra is built on a structure of commands, arguments & flags.
- Commands represent the actions.
- Args are the things.
- Flags are the modifiers for those actions.
The basic structure will be like a simple sentence.
The pattern to follow is APPNAME Command Args --Flags
or APPNAME Command --Flags Args
Examples:
git clone URL -bare
go get -u URL
npm install package --save
docker run image -d
In the following example, 'hugo' is a root command, 'server' is a command, and 'port' is a flag:
hugo server --port=1313
Similarly in one of the above examples, 'go' is a root command, 'get' is a command, '-u' is a flag and the 'URL' is an argument.
go get -u URL
Commands
A command is the central point of the application. Each interaction that the application supports will be contained in a Command. A command can have children's commands and optionally run an action.
In the example above, 'server' and 'get' are the commands.
Flags
A flag is a way to modify the behavior of a command. A Cobra command can define flags that persist through to children's commands and flags that are only available to that command.
In the example above, 'port' and '-u' are the flags.
Usage ๐ซ
First, create a directory in your GOPATH by the name of example, and inside it run the below command to initialize the modules.
go mod init example
You will notice that it created a go.mod file in the project.
Installation
Using Cobra is easy. Before going any further, first, use go get to install the latest version of the library.
go get -u github.com/spf13/cobra@latest
Once the module is created and the cobra is installed, write the following command.
cobra init
File structure
After running the above command, it will create a cmd directory, License, and the main.go file. Following is the file structure.
main.go
Here is the data inside main.go file that is created by default after initializing the cobra.
package main
import "github.com/ibilalkayy/example/cmd"
func main() {
cmd.Execute()
}
root.go
Here is the data inside the root.go file
package cmd
import (
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "example",
Short: "A brief description of your application",
Long: `A brief description of your application.`,
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
rootCmd
represents the base command when called without any subcommand. It contains the root command example, a short description, and the long description.Execute()
adds all child commands to the root command and sets flags appropriately. It only needs to happen once to the rootCmd.Init()
will define your flags and configuration settings.
Running the command
Type
go build
to create a test file inside the test directory.Type
go install
to access the GOPATH so that it runs the application.Type
example
to see the result of the application. You will see that the long description is printed out.
Add sub-commands to a project ๐
Once a cobra application is initialized you can continue to use the Cobra generator to add additional commands to your application.
The command to do this is
cobra add [any-name]
.By writing the above command, a file will be created inside the cmd directory by the name that you have given.
In my case, I have given the name first and created another file also that is called second. The creation is the same as given above and the file contains the following code by default.
first.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var firstCmd = &cobra.Command{
Use: "first",
Short: "A brief description of your command",
Long: `A longer description of your command`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("first called")
},
}
func init() {
rootCmd.AddCommand(firstCmd)
}
firstCmd
represents the first command. It contains the sub-command that is called first, short and long description.init()
will define your flags and configuration settings.Type
go install
to access the GOPATH again with this updated command so that it runs the application.
Result
After executing the go install
, type example --help
in the command prompt, and you will see the following result in which all the sub-commands are generated.
After the creation of the sub-commands, if you type
example first
OR
example second
you will see the relevant result like first called and second called. The result is printed out in each file. You can check them out.
Add flags ๐ฉ
Here I will just add a flag to the first file. The second one is your homework.
In this first file, there are two players. Each of them will be given an order by showing them a flag. If the flag is correct then they will perform a functionality otherwise there will be an error message.
Below is the updated code in the first.go file.
first.go
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var Run, Cook string
var firstCmd = &cobra.Command{
Use: "first",
Short: "A brief description of your command",
Long: `A longer description of you command`,
Run: func(cmd *cobra.Command, args []string) {
var option [2]string
option[0], _ = cmd.Flags().GetString("run")
option[1], _ = cmd.Flags().GetString("cook")
if option[0] == "run" {
fmt.Println("The player started running")
} else if option[1] == "cook" {
fmt.Println("The cook started cooking")
} else {
fmt.Println("No participants got an order. Try again!!")
}
},
}
func init() {
rootCmd.AddCommand(firstCmd)
firstCmd.PersistentFlags().StringVarP(&Run, "run", "r", "", "It is an order to a player to run")
firstCmd.PersistentFlags().StringVarP(&Cook, "cook", "c", "", "It is an order to a cook to cook")
}
In the
init()
function, two flags are added. The first one is therun
and the second one is thecook
. Each of them has a description with-r
and-c
flags.Run
andCook
are the variables that are defined above.Inside a function, an array is defined by the name of the
option
.cmd.Flags().GetString()
will get the string values of the flags that are written below in theinit()
function.If the first option is equal to run, then the player will start running. If the second option is equal to cook, then the cook will start cooking. Otherwise, there will be a message that No participants got an order. Try again!!
Now let's run the
go install
in the command prompt again.After that, type
example first -r run
. You will see that the player started running. Similarly typeexample first -c cook
. Now the cook started cooking. If you typed something else instead of run or cook, you will get an else message.
That's it.
Follow me on Hashnode, Twitter, and LinkedIn.
Thank you.