Regular Expressions and In-Place Slice Manipulation in Go

Regular expressions are very useful for parsing strings. If you need to replace a substring or split up an array, you should consider using regular expressions. I will admit that I am not an expert in regards to using them, however, I will not dismiss their usefulness. You may find the Regex Cheat Sheet very useful.

In Go, the regexp package includes many useful functions that utilize regular expressions.

Here is a simple CLI program that calculates the sum of the integer values in a string. It splits the string into a slice and then sums up all of the integer values in the slice. In this application, the string is split up using the regular expression [^0-9]+. The ^ indicates that that we do not want to match on a character that is an integer within the range of [0-9]. While the + “greedy” quantifier indicates that we want to match when there are one or more characters. In this example, we are simply delimiting the string based on non-digit values such as letters and other special characters.

One important thing to note about func (*Regexp) Split is that it creates an empty element in the slice if it starts splitting the string at the first or last element. In this example, this is handled by catching the error that is thrown when strconv.Atoi(intSlice[i]) fails to convert a string to an integer value at a given index. After an error is thrown, the bad index which is delete in place by taking the valid indexes up to the bad index and then appending the indexes that follow it. This is implemented with intSlice = append(intSlice[:i], intSlice[i:]...). After you remove the element, the length of the slice needs to be decremented.

SEE: SliceTricks

go run .\stringSum.go st1ngW1thIn7s


Golang String Sum Windows
Golang String Sum Windows

Traversing Directories Recursively and Sorting Objects by Attribute Value in Go

Lets say you would like to sort all the files in a directory, as well as its sub directories by an attribute like file size.


First, you need to recursively traverse or walk the specified directory, which is easy in Golang with the filepath.Walk() function from the path/filepath package. In order to use filepath.Walk() you need a walkfunc or walk function, which can be nested in your walk function as demonstrated in the sample program below. The walkfunc will allow you to handle errors that occur when you approach directory files or files you do not have permission to access.

Recommended tutorial: Flavio Copes – LIST THE FILES IN A FOLDER WITH GO

As you walk the directories, you will need to get the size of each file, which can be achieved using the stat() system call on Linux. In Golang, you can the os.Stat() function to get an object of type FileInfo which contains an a Size() attribute, which is what we want. As you get the file size for each file in the directory, you will need to store the relative file path and the size in bytes of each file as an object in a slice of type file objects.

Once have the file names and sizes of all of the files, you will then need to sort the files by the size attribute, either from largest to smallest or from smallest to largest, which can easily be done using sort.Slice() from the sort package. If you want sort the files from smallest to largest, you would want to use a less / < function like: sort.Slice(files, func(i, j int) bool { return files[i].size < files[j].size }). However, if you wish to sort from largest to smallest, you would use a greater / > function instead, which would look like this: sort.Slice(files, func(i, j int) bool { return files[i].size > files[j].size }). Finally, you can just simply print the desired number of files from the sorted slice.

I would say that it is important to know that in many Linux filesystems such as EXT3 and EXT4, filenames are stored in a directory table that lists files as name (key), inode (value) pairs. You can find the names of all of the files from the directory table and if you refer to a file’s inode, you can get its file size in bytes.

The relationship between the directory entry, an inode, and blocks of an allocated file
The relationship between the directory entry, an inode, and blocks of an allocated file

Here is a command line utility that takes in a directory as a string, a number of files as an int, and an order to sort them as a string. It then lists the largest or smallest files in the directory ordered by size.

Recommended tutorial: Rapid7 – Building a Simple CLI Tool with Golang

Note that since slices are references to arrays, you do not have to pass them as pointers. You can see this demonstrated with the call to sortFiles(*sortPtr, files) on line 125 as nothing is returned from it.
See: The Minimum You Need To Know About Arrays and Slices in Golang

Feed in the directory using --dir, the file count using --cnt, and the sort order which is either largest or smallest --sort

go run .\largestFiles.go --dir . --cnt 10 --sort smallest

Golang Sorted Files Windows
Golang Sorted Files Windows

On a side note, Golang’s stat() function works quite well on Windows systems, which do not have a native stat() system call.



Using Golang to Generate Custom Cover Letters

Writing a cover letter for every application is quite cumbersome. So why not automate the process? That is why I wrote a simple Go application to help with the process. The logic is quite simple as all you have to do is fill out a templated Latex .tex file and then compile it. If you want to go even further, the process for generating a custom cover Email is almost the same. Instead of using a templated out .tex file, you just use a templated out .html file.

For this tutorial, I recommend using the popular Moderncv Classic LaTex template. If you wish to use this LateX template for your resume as well, I recommend moving the cover letter and CV / resume sections in main.tex to seperate files. To do so, you can use the \include LateX command. StackExchange: When should I use \input vs. \include?

Here is an example of a templated out cover letter .tex file

First, you take in the arguments, that are dependent on the position, as command line flags. Read this tutorial on building a simple CLI tool.

Using the provided arguments, you can generate default statements.

You might also want to get the current date. Read Date and time formatting in Go.

The user specified and generated values are then passed into a map which is used to fill in the templated out .tex file.

You then read the templated out text file and when a key attribute in the map is found in the templated out file, you replace it with it’s corresponding value attribute.

Now you want to save the string to a new .tex file.

If you wish to just send a cover Email, you do not have to write to a new file as the string can serve as the body of the Email. As already stated, you should use a templated .html file to generate cover Emails.

Now to build the .pdf file, you will have to call an external command to run pdflatex. Read this tutorial on running shelled out commands in Golang.

If you are an over achiever and would like to be able to automatically send generated cover Emails, the gomail library makes this easy. Read the gomail README.

If you would like to keep track of where you sent your applications out, you can simply write to a log file. I recommend writing to a CSV based log file as they import easily into Microsoft Excel and LibreOffice Calc.

You can also pass an “application” object by reference instead of passing variables by value.

You can find my full implementation with sample template files in this git repository.