How to Build a Command-Line Dictionary App in Golang Using an API
Golang is one of the most in-demand languages in the Tech market right now, and there are few better ways to learn the basics of Golang then to make a Command Line App using an external API. IN this read, you will learn how to make a dictionary app that is used from your terminal by using a dictionary API. You will learn about APIs in general, about GET requests, about how Golang handles JSON data, and basics of structs. Let’s get started!
Setting Up the Project
Before we start coding, ensure you have Golang installed on your system. If you haven’t installed it yet, follow the instructions on Go’s official website.
After installing Golang, and adding it to path, in a preferably new folder, create a new file, you can name it anything, just ensure that the extension is .go. Next, open the terminal in your directory, and write go mod init filename.
What this does is create a Golang module that helps us in installing external Golang libraries and modules made by other developers.
Next, you’ll need to install the fatih/color
package to add some color to our CLI output. This is an external package that will give colors to text rather than them being only black/white. You can do this by running in the same terminal:
go get github.com/fatih/color
After this, your folder should look like this:
filename.go
go.mod
go.sum
Right now, only the .go is important, let’s start coding!
Writing the Code
Let’s break down the main steps of our CLI dictionary app:
Step 1: Importing Required Packages
We begin by importing the necessary Go packages:
package main
import (
"encoding/json"
"fmt"
"io"
"math/rand"
"net/http"
"os"
"github.com/fatih/color"
)
The encoding/json
package helps with formatting JSON data received by us when we send a request to the API, fmt
is the standard Golang package for displaying things to the user. io
stands for input/output which helps in taking input from user or sending an output. math/rand
is a module that helps to generate random values. net/http
helps us to actually send a GET request to the API, and it also handles a lot of utf-8 encoding and decoding so that we don’t have to deal with complex problems at such a stage. os
is required when building Command line Apps as it allows us to directly communicate with the Terminal and any external argument the user might pass through when calling our App. color
is the external module that we just installed that will give an interesting color to the output.
Step 2: Generating Random Colors
To make our CLI output visually appealing, we define a function to generate random RGB values:
func generateRandom() int {
return rand.Intn(256)
}
This function returns a random integer between 0 and 255, which we later use for setting text colors.
Step 3: Defining the Word Structure
We define a struct to map the JSON response from the dictionary API:
type Word struct {
Word string `json:"word"`
Meanings []struct {
PartOfSpeech string `json:"partOfSpeech"`
Definitions []struct {
Definition string `json:"definition"`
Synonyms []string `json:"synonyms,omitempty"`
Antonyms []string `json:"antonyms,omitempty"`
} `json:"definitions"`
} `json:"meanings"`
}
In Golang, struct is defined as type structName struct
which is a bit different from many Programming languages where the type/typedef keyword is optional, and the struct keyword is before the name.
As Golang is a JSON friendly language, we use structs to as closely map the JSON output structure as possible. Normally you should first analyze the JSON, and then make your struct, but for this read, I have done that for you.
Struct Structure:
The Word is the word given by us, i.e. the user to the dictionary. Meanings is an array of structs, with each different meaning of the word having a single PartOfSpeech string, and another array of structs, called Definitions, each of which has a definition string, and an array of synonyms and antonyms. You will notice `json:”word”
` along the declaration of the struct, and similar strings inside the struct. This is a cool feature in Golang that helps us to automatically map a struct to the JSON output, and without the availability of such a feature, we would have to manually create a struct and then parse the JSON and assign each variable of the struct its value.
Step 4: Handling User Input
The program allows users to input a word as a command-line argument. If no word is provided, it defaults to “Hello”. This is where the os
module comes in use as os.Args
returns an array, and if the length of the array is two or greater, which means two words are entered in the terminal, as the first word is the command to run this app. The second is the word the user wants the Dictionary to tell him/her details about.
func main() {
word := "Hello"
if len(os.Args) >= 2 {
word = os.Args[1]
}
Step 5: Fetching Data from the API
The program makes an HTTP GET request to the Dictionary API. http.Get
is a function that will return two values, result, and an error. in the if statement we are checking if the error is not nil,
which, if it isn’t, means that some error has occurred and our request has failed.
res, err := http.Get("https://api.dictionaryapi.dev/api/v2/entries/en/" + word)
if err != nil {
panic(err)
}
defer res.Body.Close()
If the request fails, the program will exit with an error message.
defer res.Body.Close()
means that the program will free the memory allocated to the request and the response after it is closed.
Step 6: Reading and Parsing JSON Data
The response body is read and converted into a Go struct:
body, err := io.ReadAll(res.Body)
if err != nil {
panic(err)
}
var words[] Word
err = json.Unmarshal(body, &words)
if err != nil {
panic(err)
}
io.ReadAll()
is used to read the response and decode it to actual JSON text and it also returns an actual value, body
and an error.
Then we make our struct with var words[] Word
and use the json.Unmarshal
function which returns only an error, not any actual value because we pass our struct as a pointer and the function changes our struct, and does not return a new struct.
Step 7: Displaying the Word and Its Meanings
Finally, the program loops through the response and prints the word definitions in a randomly chosen color:
color := color.RGB(generateRandom(), generateRandom(), generateRandom())
for _, word := range words {
color.Printf("Word: %v \n", word.Word)
for _, meaning: = range word.Meanings {
color.Printf(" Part Of Speech: %v \n", meaning.PartOfSpeech)
for _, definition: = range meaning.Definitions {
color.Printf(" Definition: %v \n", definition.Definition)
}
}
}
}
This part of the code ensures the definitions are printed with colorful formatting, making them easier to read.
In Golang, for loops can be used many ways, here with for _, word := range words
we get each index and word in words, as we don’t have any use for index, we use assign it to _, which signifies that this variable is not used any further.
We have made an array of struct Words called words because the JSON output gives a list of different meanings of the same words. We loop through the array for each word, and display the output.
Running the CLI Dictionary
Once you’ve written the code, compile and run the program using:
go run filename.go amazing
This should return definitions for the word “amazing” from the API and display them in the terminal with colorful formatting.
Converting .go to .exe:
go build -o myprogram.exe myfile.go
This command in your terminal will create an exe file that can be then added to your system’s path, and then can be used directly from your terminal.
To do that, open a new Terminal/CMD window and run it as administrator, and then run this command:
setx PATH "%PATH%;C:\path\to\your\exe"
where “path\to\your\exe” is the path to the .exe file you just created. Make sure to enter the complete path.
Conclusion
I hope this read taught you about the basics of Golang, API, and GET requests. Follow me for more of these articles, and ask any questions you have in the comments.
GitHub Link for this code:
https://github.com/TheJashShah/Golang-Projects/tree/main/CLIs%2FDictionary-CLI