DEV Community

Iza Rokita for Railwaymen

Posted on • Updated on • Originally published at blog.railwaymen.org

Golang Tutorial - How to Implement CLI App in 4 Steps Using Cobra?

According to the research, there are between 500 and 2000 active general-purpose programming languages around the world. That's a crazy lot! Yet - the new languages still appear, dethroning some of the old ones. That's why as a self-aware developer you should keep an eye on the latest trends on the market because who knows, maybe the language that you are developing your apps in today, won't be as desirable in the future?

golangtutorial

And even if it's not the case - programmers today are required to know more than just one programming language. It's also good for your mental health (avoiding getting burned out) to know some other technologies, that you can experiment in. So if you are looking for some new programming language, to expand your horizons - we have some proposition for you!

Golang introduction - basic features & language advantages

Go is an open-source programming language (also known as Golang) and it has been developed by Google in 2009. The language Go speed, simplicity, and reliability make it the perfect choice for all kinds of developers. It is used to implement any kind of app: web app, CLI, machine learning tools.

The main reasons why I have decided to use the Go language are:

  • fast performance

Golang is compiled to machine code and its compilation is very fast. The language links all dependency into a binary file.

  • easy concurrency model

This makes it easy to progress with multiple tasks at the same time. Concurrency is an integral part of Go, supported by goroutines, channels.

  • easiness to learn

Compare to other programming languages like C, C++, Rust etc., Go is easy to learn.

  • cross-platform

You can write code in any environment you like - OS-X, Linux, FreeBSD, or Windows.

What is Golang good for & companies that use it

Some of the biggest companies worldwide have already discovered the potential of Go, using it for their business purposes. You can find some examples of them below:

Google
digitalocean.com
Airbrake
Atlassian
and more other

Golang is great to build the Command Line Interface (CLI) app. In this tutorial, I'm going to present step by step how to implement that CLI app using Go lang and Cobra package. Because I believe it is the best way to learn Golang - based on a real-life challenge.

There are many CLI apps implemented using Golang ie. Docker, Kubernetes, Hugo. The biggest advantage of this kind of apps are:

the app is lightweight
it's easy to run using terminal scripts i.e zsh, bash
the app is fast
there are no dependencies
it is best for task-based automation

Golang tutorial - the app purpose & library introduction

The Golang "duplicate" app

The app in the tutorial will provide the main features:

1) create dir for files
2) copy files to the destination directory

I assume that You have already installed a Golang and set up a development environment for it. The library which is the best match in the case of the CLI app is Cobra.

Golang tutorial - Cobra library introduction

Before we start using the Cobra library we need to get to know the concepts behind it.

"Cobra is built on a structure of commands, arguments & flags. Commands represent actions, Args are things and Flags are modifiers for those actions." - Cobra github

The structure will be like

APPNAME Command Args --flags

Example app execute in console

docker ps -a
Hugo new site example.com

Go programming tutorial - let's start coding!

If you want to learn golang, this tutorial will show you how you can tackle a specific challenge considering CLI apps, that as developers we often encounter. Enjoy and feel free to let me know in the comment section if anything requires further elaboration!

Step 1: Creating the project in Golang

Cobra library provides initializator command for the new project. Let's init base CLI structure using cobra.

cobra init --pkg-name github.com/michalsz/duplicator
duplicator

Inside the project dir.

cd duplicator

Add new action duplicate

cobra add duplicate

Structure of the project

duplicate/
  cmd/
    root.go
    duplicate.go
  main.go

The main.go is the entry point of the CLI. Inside the main.go it is calling the Execute function of the

cmd/root.go
.
package main

import "github.com/michalsz/duplicator/cmd"

func main() {
        cmd.Execute()
} 

Let's look to root.go The main part of root.go is our command rootCmd where we define it.

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
    Use:   "duplicator",
    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) { },
} 

Build the app without defining any code for root command

go build -o  duplicator main.go && ./duplicator duplicate

As a result we get only print in terminal

duplicate called

Step 2: Let's define a flag for our duplicate command

Define var 'fileExt' to store file extension which kind of file we are going to copy.

var fileExt string

    // duplicateCmd represents the duplicate command
    var duplicateCmd = &cobra.Command{

Add definition flag to init() function in duplicate.go file. Look that the flag extension is required.

duplicateCmd.Flags().StringVarP(&fileExt, "extension", "e", "", "file extension is required")
    duplicateCmd.MarkFlagRequired("extension")

And print fileExt var in Run section of our command

Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("duplicate called")
        fmt.Println(fileExt)
    },

Let's build and run it.

go build -o  duplicator main.go && ./duplicator duplicate -f txt

As result we get print in console

duplicate called
  txt

Step 3: Let's define a new flag 'dirName' which store handle dir name where the file will be duplicated.

var dirName string

func init() {
    fmt.Println("init called")
    duplicateCmd.Flags().StringVarP(&fileExt, "extension", "e", "", "file extension is required")
    duplicateCmd.MarkFlagRequired("extension")
    duplicateCmd.PersistentFlags().StringVarP(&dirName, "dirname", "d", "copied_files", "dir to copie")
    rootCmd.AddCommand(duplicateCmd)

}

We see that the flag -d is not required and has default value copied_files for the dir.

Step 4: Let's add a new command which prints the version of our app

cobra add version

Add version function to version.go file.

func version(){
    fmt.Println("v0.1")
}

And call it in Run section.

Run: func(cmd *cobra.Command, args []string) { fmt.Println("version called") version() },

Summary and conclusion

I have decided to use the Cobra package since it is really easy to integrate it with the base code of any application. The best in Cobra package is that it organizes commands into dedicated command file ie. duplicate.go The package also auto-generate man pages for your command. I see big potential in this package.

Are you still hungry to get to know better as many programming languages as you can? Wonderful, as we have a comparison of two very popular ones prepared for you! Ruby vs PHP - which one will win the ultimate battle for the developer's heart?

This post has been originally published on a Railwaymen blog here.

Top comments (0)