DEV Community

Shanmukh Sista
Shanmukh Sista

Posted on • Originally published at shanmukhsista.com on

CLIs Made Simple : Guide to writing a beautiful CLI in GoLang

Over the last few years, i've been fascinated by the type of Applications and services one could write in Go. Using GoLang I've implemented RPC Services, REST APIs, Web UIs and Cloud Functions using extremely simple programming paradigms. The main reason i enjoy GoLang is the simplicity it has to offer. At the same time, it's extremely powerful to write a wide variety of applications. It is known to be a systems language, but it's not limited in any way.

In this article, i'll guide you through a simple CLI app that can be written in less than 30 minutes in GoLang. Before we dive deeper, here are the requirements to work on this.

  1. GoLang ( 1.16 -https://golang.org/doc/install )
  2. Text Editor ( https://code.visualstudio.com/ )

This guide doesn't go in the details of Coding in GoLang. It gives a high level overview of implementing a CLI as a starting point to your application.

Create a New Project

This is the first step for our application. To setup a new project, create a new folder on your system. Execute the commands below to get started.

mkdir cliapp
# Create a Go Project.
go mod init github.com/shanmukhsista/cliapp
Enter fullscreen mode Exit fullscreen mode

This creates a new Go Project. A file named go.mod should be created after this.

We'll be using Cobra ( https://github.com/spf13/cobra ) to create our CLI. Another awesome library that helps with this whole process, and provides a lot of capabilities out of the box ( help text, cli argument parsing ... )

Run the following command to add Cobra as a Dependency.

go get -u github.com/spf13/cobra
Enter fullscreen mode Exit fullscreen mode

Initialize Cobra CLI Project

cobra init --pkg-name github.com/shanmukhsista/cliapp
Your Cobra applicaton is ready at ...
Enter fullscreen mode Exit fullscreen mode

Upon successful execution, your folder structure should look like the image shown above. Below is a summary of these files.

  • main.go - This is the entry point for our app. Any initialization before the CLI runs can be done within this file.
  • cmd Folder - This folder contains all the commands, and sub commands as separate go files. Try executing the following command, and see how the folder structure changes.
# Add a root command 
cobra add setup
# Add a child command to the root command.
cobra add tests -p setupCmd
Enter fullscreen mode Exit fullscreen mode

Time to Test our app!

So far, our application doesn't have any specific logic. Let's build the app and see how our CLI looks like at this point. Run the following command to build and run.

# Build our app with 
go build -o cliapp main.go
./cliapp

$ ./cliapp
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:
  cliapp [command]

Available Commands:
  completion generate the autocompletion script for the specified shell
  help Help about any command
  setup A brief description of your command

Flags:
      --config string config file (default is $HOME/.cliapp.yaml)
  -h, --help help for cliapp
  -t, --toggle Help message for toggle

Use "cliapp [command] --help" for more information about a command.
Enter fullscreen mode Exit fullscreen mode

This is the output that is generated by Cobra when your command is executed. Notice that the setup command is generated as a top level command. Try executing another command

./cliapp setup -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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:
  cliapp setup [flags]
  cliapp setup [command]

Available Commands:
  tests A brief description of your command

Flags:
  -h, --help help for setup
Enter fullscreen mode Exit fullscreen mode

Add Some Logic And Parameters

Until now, our application doesn't really do anything. Cobra gives specific starting points where code can be written and application logic can be executed.

Let's write some code within the setup method.

It can be seen that all of the commands have their own files within the cmd folder. To write some logic to the setup command, try opening the file cmd/setup.go and add code within the ( Run: func(cmd *cobra.Command, args []string) block :

// setupCmd represents the setup command
var setupCmd = &cobra.Command{
    Use: "setup",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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.`,
    Run: func(cmd *cobra.Command, args []string) {

        // Add any custom code here.
        // This gets executed whenever this command is called.

        fmt.Println("setup called")
    },
}
Enter fullscreen mode Exit fullscreen mode

This is where all the logic can go. In a production setting, this can act as an entry point to the package where the actual logic exists.

Parameters

Practically speaking, every CLI app takes in one or more than one command line argument. Let's try to add one to our setup method. In this case, let's take an argument --app-name as our argument. We'll print out this when our command executes.

Define a new variable in cmd/setup.go


import (
    "fmt"

    "github.com/spf13/cobra"
)

var AppName string // Store App Name Argument
Enter fullscreen mode Exit fullscreen mode

The goal here is to parse --app-name argument, and automatically assign it to the variable defined above. To do so, add the following command to the init method.


func init() {
    rootCmd.AddCommand(setupCmd)
    // Define a new flag for App Name
    setupCmd.Flags().StringVarP(&AppName, "app-name", "a", "", "App Name")

}

Enter fullscreen mode Exit fullscreen mode

Now use this variable in the actual execution logic. In this case, we print the app name within the Run Method.

Run: func(cmd *cobra.Command, args []string) {

        // Add any custom code here.
        // This gets executed whenever this command is called.

        fmt.Println("setup called with app name " + AppName)
    },
Enter fullscreen mode Exit fullscreen mode

Build and run the program to view App Name printed on the screen.

go build -o cliapp main.go
./cliapp setup --app-name "New CLI App"
setup called with app name New CLI App
Enter fullscreen mode Exit fullscreen mode

This process can be repeated for any number of arguments, commands, and child commands. Cobra really simplifies a building CLIs to enable some powerful applications that can run in any environment. Built executables can be copied and run on any target system without any underlying VM / service.

Top comments (1)

Collapse
 
bhumit070 profile image
Bhoomit Ganatra

please add source code if possible