Building a Go Command Line Tool

2 hours
  • 5 Learning Objectives

About this Hands-on Lab

Go is a great language for building tools. In this learning activity, you’ll go through the process of building a complete command line application. By the time we’ve finished this activity, you’ll have gone from a list of features and a desired user experience to having a fully built CLI written in Go. You’ll learn how to create custom structs and work with JSON along the way.

Learning Objectives

Successfully complete this lab by achieving the following learning objectives:

Create `hr` Package within the `$GOPATH`

Our project needs to be created. We’ll do so by creating a directory for us to add our source files.

Create `main` Package with `User` Struct to Hold Information Parsed from `/etc/passwd`

Our list of users has a very specific shape, and we can represent that shape using a struct. Let’s create a main.go file and add a User struct to it that handles the name, id, home, and shell values.

Parse Information from `/etc/passwd` into a Slice of `User` Structs

We’re going to create a function called collectUsers that parses the /etc/passwd file and returns a slice of User structs. Now we’ll be able to use the user information in the main portion of our program.

Define and Parse the `path` and `format` Flags

To keep things manageable, we’re going to define our flags in a separate function that performs the following steps:

  1. Defines the path and format flags
  2. Parses flags
  3. Validates the user-provided information. If there is an error, then exits and displays an error.
  4. Returns path and format values
Write User Information as CSV or JSON Information Either to a File or stdout

We want to write the content to either a file or stdout, and thankfully they both adhere to the io.Writer interface. Because of this interface, we can keep our writing logic ignorant of whether we’re writing to a file or stdout. Here’s what we need to implement, in order:

  1. Parse flags into variables using parseFlags.
  2. Gather users using collectUsers.
  3. Create an io.Writer variable.
  4. Assign a value to the io.Writer variable based on the path variable. This variable should be a file if the path variable is set or os.Stdout otherwise.
  5. If the format variable is "json", utilize the json.MarshalIntent function to pretty-print the users to a slice of bytes before using the Write function on our io.Writer variable.
    OR
  6. If the format variable is "csv", write the header line to the io.Writer, create a new csv.Writer from the io.Writer, and write a line for each of the users.

Additional Resources

You've been asked to create a tool to export a system's user information. The command will be able to export user names, IDs, home directories, and shells as either JSON or CSV. This command will not include information about system users (users with IDs under 1000). By default, the command will display the information as JSON to stdout, but the -format flag will allow a person to specify csv as the export type. Additionally, a file can be specified by using the -path flag. Here are the various ways the tools can be used:

$ hr -format=csv -path=path/to/users.csv
$ hr -path=path/to/users.json
$ hr
[
  {
    "name": "cloud_user",
    "id": 1002,
    "home": "/home/cloud_user",
    "shell": "/bin/bash"
  },
  {
    "name": "kevin",
    "id": 1003,
    "home": "/home/kevin",
    "shell": "/bin/zsh"
  },
]
$ hr -format=csv
name,id,home,shell
cloud_user,1002,/home/cloud_user,/bin/bash
kevin,1003,/home/kevin,/bin/zsh

Hints:

Go provides numerous libraries that will be useful to implement this tool. Some to consider investigating would be:

  • encoding/json: The built-in JSON encoding/decoding library.
  • encoding/csv: The built-in CSV encoding/decoding library.
  • strconv: The standard library package for converting strings to other types.
  • strings: A library for working with strings. Useful for changing a string to all lowercase letters.

The information we want can be found in the /etc/passwd file. The lines in this file look like this:

cloud_user:x:1002:1003::/home/cloud_user:/bin/bash

Notice this format looks like CSV except that the separator is a colon instead of a comma.

What are Hands-on Labs

Hands-on Labs are real environments created by industry experts to help you learn. These environments help you gain knowledge and experience, practice without compromising your system, test without risk, destroy without fear, and let you learn from your mistakes. Hands-on Labs: practice your skills before delivering in the real world.

Sign In
Welcome Back!

Psst…this one if you’ve been moved to ACG!

Get Started
Who’s going to be learning?