Getting started with CLI's using Golang.
Introduction
In this blog we are going to get started with CLI using Golang and Cobra CLI. We are just going to make a simple Quiz game CLI and get friendly with the Cobra-CLI library.
Why Cobra-CLI?
Cobra is both a library for creating powerful modern CLI applications and a program to generate applications and CLI applications in Go. Cobra powers most of the popular Go applications including CoreOS, Delve, Docker, Dropbox, Git Lfs, Hugo, Kubernetes, and many more. With integrated command help, autocomplete and documentation.
Prerequisites
To continue with tutorial, firstly you need to have Golang and Cobra-CLI installed.
Installation
For installing Cobra-CLI you can go to Cobra or run
go install github.com/spf13/cobra-cli@latest
in the terminal.
Initializing the Project
After completing the Installation part to get started make a folder for eg. go_quiz
, run the given command
go mod init github.com/Siddheshk02/go_quiz
In place of Siddheshk02
use the name in which your project directories are. Now the structure will look like this
Cobra-cli init
This command initializes the CLI and make a main.go
file along with cmd
folder containing root.go
The main.go file will contain this code
package main
import "github.com/Siddheshk02/go_quiz/cmd"
func main() {
cmd.Execute()
}
This means the main cli commands implementation will be in cmd
which is called through main.go
.
Make the following changes in the root.go
file.
package cmd
import (
"os"
"github.com/spf13/cobra"
)
var rootCmd = &cobra.Command{
Use: "go_quiz",
Short: "A Simple Quiz game CLI",
Long: `A Simple Quiz game CLI using Golang.`,
}
func Execute() {
err := rootCmd.Execute()
if err != nil {
os.Exit(1)
}
}
func init() {
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
In root.go
, function Execute
gets called from main.go
and it executes the rootCmd
. Use
is used to define the command to be used and Short
and Long
contains the information or description for the Command in short and long format respectively.
Now run go run main.go
or go build .
and .\go_quiz
or go_quiz
.
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz> go run main.go
A Simple Quiz game CLI using Golang.
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz> go build .
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz> .\go_quiz
A Simple Quiz game CLI using Golang.
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz>go_quiz -h
A Simple Quiz game CLI using Golang.
Usage:
go_quiz [flags]
go_quiz [command]
Available Commands:
completion Generate the autocompletion script for the specified shell
help Help about any command
start Starting a new Quiz
Flags:
-h, --help help for go_quiz
-t, --toggle Help message for toggle
Use "go_quiz [command] --help" for more information about a command.
Now let's make a csv file data.csv
in the go_quiz
directory, to store the questions and answers for the quiz.
Store the following values in the file.
5+5,10
7+3,10
1-1,0
8+3,11
1+2,3
8-6,2
3-1,2
1+4,5
5-1,4
2+3,5
3+3,6
7-4,3
5+2,7
9-2,7
4+8,12
1+8,9
Lets make a new command which will be used to start a Quiz.
for adding a new command run this code Cobra-cli add start
, here start
is the new command made.
This will create a new file start.go
in the cmd folder.
Make the following changes in the start.go
file
package cmd
import (
"fmt"
"github.com/spf13/cobra"
)
var startCmd = &cobra.Command{
Use: "start",
Short: "Starting a new Quiz",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("start called")
},
}
func init() {
rootCmd.AddCommand(startCmd)
}
let's try running our new command. Run go build .
in the terminal and then run go_quiz start
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz>go_quiz start
start called
you can also try running go_quiz start -h
.
Now, for the main implementation of the Quiz game, we will make a folder pkg
in the project directory i.e. go_quiz
and a file quiz.go
in the pkg
folder.
In the quiz.go
make a functionQuiz
that returns a string res
func Quiz() (res string) {
return res
}
This function will be called in the start.go
as :
Run: func(cmd *cobra.Command, args []string) {
res := pkg.Quiz
},
Now, let's code in the Quiz
function in quiz.go
Firstly, we need to open and read the data.csv
file to get the questions and there answers.
package pkg
import (
"encoding/csv"
"errors"
"fmt"
"io"
"log"
"os"
"strconv"
)
func Quiz() (res int, err error) {
res = 0
f, err := os.Open("C:/Users/Admin/Go/src/github.com/Siddheshk02/go_quiz/data.csv")
if err != nil {
log.Fatal(err)
}
defer f.Close()
csvReader := csv.NewReader(f)
var ans int
for {
rec, err := csvReader.Read()
if err == io.EOF {
break
}
if err != nil {
log.Fatal(err)
}
fmt.Print(rec[0] + " : ")
c, _ := strconv.Atoi(rec[1])
fmt.Scanf("%d\n", &ans)
if ans == c {
res = res + 1
fmt.Println("correct")
continue
} else {
err = errors.New("Incorrect Response!!")
break
}
}
return res, err
}
Here, we are taking the questions and answers in rec
which is a string array, so for each iteration in the loop the rec
array takes question in rec[0]
and answer in rec[1]
.
Then for comparing the user input ans
with the original answer i.e. rec[1]
, we first convert rec[1]
into integer type as ans
is in integer whereas rec
is string.
A res
variable is created to store the result count, which is returned along with err
error after completing the quiz or after giving an Incorrect response.
So, the start.go
will look like the following code after all changes:
Run: func(cmd *cobra.Command, args []string) {
res, err := pkg.Quiz()
if err != nil {
fmt.Println(err)
fmt.Printf("Your Score is %d", res)
} else {
if res == 16 {
fmt.Println("Congrats!, you got all questions Correct")
}
fmt.Printf("Your Score is %d", res)
}
},
Now, run go build .
and then go_quiz start
to test the CLI.
C:\Users\Admin\Go\src\github.com\Siddheshk02\go_quiz>go_quiz start
5+5 :
Enter the answers after getting the question :)
If all the given responses are correct
.
.
.
1+8 : 9
correct
Congrats!, you got all questions Correct
Your Score is 16
And if any of the response is Incorrect :(
.
.
7+3 : 10
correct
1-1 : 0
correct
8+3 : 1
Your Score is 3
The complete code is saved on GitHub
Conclusion
In this tutorial we learnt how to create a command-line application with Go and Cobra. In the next upcoming tutorial , we will learn how to add flags, commands, etc. and build more such amazing stuff.
If you enjoyed this article and you'd like more, consider following Siddhesh on Twitter to get the latest updates.
Congratulations, you did great. Keep learning and keep coding :)
Subscribe to my newsletter
Read articles from Siddhesh Khandagale directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by
Siddhesh Khandagale
Siddhesh Khandagale
I am a Developer experienced in building Web Apps and CLI using Golang. I'm also experienced in Laravel development