How to Create a CLI in Go in Minutes
Get up and Go with this quick and effective tutorial.
Join the DZone community and get the full member experience.
Join For FreeIn our day-to-day work, we are used to using nifty tools in the command line. We are surrounded by CLI (Docker, Kubectl, Terraform, AWS, etc.). We will see in this tutorial, that in just a few minutes, it is possible to create a CLI with Go language and the Cobra library. Are you ready?
Why Go?
Go, created in 2009, and used in production by thousands of companies around the world (including Uber, Lyft, Slack, Pinterest ... and of course Google), is becoming the preferred language of the Cloud. It is easy to install, provides libraries and tools, and is fast to compile and not very greedy in memory.
With its ecosystem riddled with tools and CLIs, it would be wrong not to put Go in our toolbox. If you have not started Go yet, you can start by doing the interactive "tour de go" tutorial: https://tour.golang.org.
As you will see in this article, writing a CLI with GO is a breeze!
You may also like: Golang Tutorial: Learn Golang by Examples.
Prerequisites:
Go!
The first step is, if you have not already done so, to install Go on your machine. For this, you can follow the installation procedure on the official website or go through GVM. GVM is a very practical version for Go, which allows you to update your version of Go by specifying which version you want.
Installation:
For bash:
bash < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
For zsh:
zsh < <(curl -s -S -L https://raw.githubusercontent.com/moovweb/gvm/master/binscripts/gvm-installer)
Usage:
$ gvm
Usage: gvm [command]
Description:
GVM is the Go Version Manager
Commands:
version - print the gvm version number
get - gets the latest code (for debugging)
use - select a go version to use (--default to set permanently)
diff - view changes to Go root
help - display this usage text
implode - completely remove gvm
install - install go versions
uninstall - uninstall go versions
cross - install go cross compilers
linkthis - link this directory into GOPATH
list - list installed go versions
listall - list available versions
alias - manage go version aliases
pkgset - manage go packages sets
pkgenv - edit the environment for a package set
The GVM command that will interest us especially is the command gvm install, it is used like this:
$ gvm install [version] [options]
Go installation:
$ gvm install go1.12.9 -B
$ gvm use go1.12.9 --default
In your .zshrc or .bashrc file, set your $GOROOT and $GOPATH environment variables. Here is an example :
[[ -s"$HOME/.gvm/scripts/gvm" ]] && source"$HOME/.gvm/scripts/gvm"
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=${PATH}:$GOBIN
That's it, Go is installed, its version manager also, it's time to get to the heart of the matter and create our first CLI.
Cobra
Cobra is both a library for creating powerful modern CLI applications and a program for generating applications and batch files.
Using Cobra is easy. First, use the go get command to download the latest version. This command will install the cobra generator executable with the library and its dependencies:
$ go get -u github.com/spf13/cobra/cobra
The cobra binary is now in the bin/ directory of your $GOPATH, which is itself in your PATH, so it can be used directly.
We will start by generating our first application with the command cobra init followed by the package and the name of your app. The command will generate the application with the correct file structure and imports.
$ cd $GOPATH/src
$ cobra init github.com/scraly/hello-world
Using config file: /home/scraly/.cobra.yaml
Your Cobra application is ready at
/home/scraly/git/src/github.com/scraly/hello-world
Give it a try by going there and running `go run main.go`.
Add commands to it by running `cobra add [cmdname]`.
Your application is initialized, a main.go file and a cmd/ package has been created:
$ cd github.com/scraly/hello-world
$ tree
.
├── cmd
│ └── root.go
├── LICENSE
└── main.go
1 directory, 3 files
At the execution of our CLI we want to display:
* a short description
* a long description
* using our app
To do this, simply modify the cmd/root.go file:
// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
Use: "hello-world",
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) { },
}
Now, we want to add a start command in our small application. For that, we will use the add command of the cobra CLI:
$ cobra add start
Using config file: /home/scraly/.cobra.yaml
start created at /home/scraly/git/src/github.com/scraly/hello-world/cmd/start.go
/!\ Warning: Note that the command names must be in camelCase format.
Once you have executed these three commands, you get an application structure similar to this one:
$ tree
.
├── cmd
│ ├── root.go
│ └── start.go
├── LICENSE
└── main.go
At this point, you can run go run main.go to run your application:
$ 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.
Usage:
hello-world [command]
Available Commands:
help Help about any command
start A brief description of your command
Flags:
--config string config file (default is $HOME/.hello-world.yaml)
-h, --help help for hello-world
-t, --toggle Help message for toggle
Use "hello-world [command] --help" for more information about a command.
Then, run main.go to run the start command:
$ go run main.go start
start called
If we had created another command, for example, cobra add config
, we could also test the command by typing go run config.go
.
We will now modify the cmd/start.go file, with our own code, so that our application displays the message we want for the start command:
var startCmd = &cobra.Command{
Use: "start",
Short: "This command will show you a hello world message",
Long: `Welcome in start command, this cmd will display to you a hello world message.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Hello world, start have been called!")
},
}
We can test the help of our start command right now:
$ go run main.go start -h
Welcome in start command, this cmd will display to you a hello world message.
Usage:
hello-world start [flags]
Flags:
-h, --help help for start
Global Flags:
--config string config file (default is $HOME/.hello-world.yaml)
Then, run the start command to see the updated message:
$ go run main.go start
Hello world, start have been called!
We can also display the help message from our start command:
$ go run main.go start -h
Welcome in start command, this cmd will display to you a hello world message.
Usage:
hello-world start [flags]
Flags:
-h, --help help for start
Global Flags:
--config string config file (default is $HOME/.hello-world.yaml)
Your application is ready, you just have to build/install it in your $GOPATH then use it:
$ go install
$ hello-world start
Hello world, start have been called!
Want to go further?
We will add a say command and a hello subcommand to make our little program say: "hello, world!"
Let's add our say command:
$ cobra add say
say created at /Users/uidn3817/go/src/github.com/scraly/hello-world/cmd/say.go
Let's edit this file to warn the user that the say command is not used alone. Just replace the Run method with this one:
RunE: func(cmd *cobra.Command, args []string) error {
return errors.New("Provide item to the say command")
},
Next, we add hello sub command:
$ cobra add hello -p 'sayCmd'
hello created at /Users/uidn3817/go/src/github.com/scraly/hello-world/cmd/hello.go
Let's modify the hello.go file that has just been generated, so that the CLI can display "hello, world!"
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("hello world !")
},
Now, we need to install the app again in our machine:
$ go install
And we test again:
$ hello-world say
Error: Provide item to the say command
Usage:
hello-world say [flags]
hello-world say [command]
Available Commands:
hello A brief description of your command
Flags:
-h, --help help for say
Global Flags:
--config string config file (default is $HOME/.hello-world.yaml)
Use "hello-world say [command] --help" for more information about a command.
Provide item to the say command
And now we can just test again our app with the say command and hello sub command:
$ hello-world say hello
hello world !
And that's it, you coded your CLI in Go in a few minutes; it's a good start! :-)
If you liked this article, I'll write several articles to go further with your first CLI and your first application in Go!
Further Reading
Opinions expressed by DZone contributors are their own.
Comments