Learn Go by creating a tool — Part 1
In this series of articles we will learn how to create a tool in Go, by following this tutorial will not learn you Go from zero, nor will…
In this series of articles we will learn how to create a tool in Go, by following this tutorial will not learn you Go from zero, nor will learn you everything but should make you feel comfortable start using Go to solve a problem, lets start!.
Calculating MD5 hash of a file
The tool purpose will be to calculate the MD5 hash of of a file in a very similar way like the md5sum command we can find in many OSes like Linux and Macos, an MD5 hash is an one way function that turns any input to to a fixed 128-bit fingerprint.
How the tool will work
We will create many revisions of the tool, each revision will be more complex than the previous and with more features, our first version of the tool will have the sole purpose of reading a file and calculating its MD5 hash.
The code
Here is the code for our first version, we will explain how it works line by line
package main
import (
"crypto/md5"
"fmt"
"os"
"io"
)
func main() {
if len(os.Args) < 2 {
fmt.Println("Usage md5sum <file>")
return
}
filename := os.Args[1]
file, err := os.Open(filename)
defer file.Close()
if err != nil {
fmt.Println(err)
return
}
hash := md5.New()
if _,err := io.Copy(hash, file); err != nil {
fmt.Println(err)
return
}
sum := hash.Sum(nil)
fmt.Printf("MD5 (%s) = %x\n",filename,sum)What package main does
package main marks the file as the entry point file for your program, the compiler will then look for a function called function main() {...}
What import does
import is used to specify the libraries that will be used from our program
What func main does
It is the first function that will be executed, it is the entrypoint of our program
Counting number of arguments
This if statement counts the number of arguments given from the command line, if the number is less than 2 (the program filename and the file that we want to calculate its md5 hash) will return from the main function and exit to the system.
if len(os.Args) < 2 {
fmt.Println("Usage md5sum <file>")
return
}Opening the file to read
Next we want to open the file to read it
filename := os.Args[1]
file, err := os.Open(filename)
if err != nil {
fmt.Println(err)
return
}
defer file.Close()The filename variable will contain the second command line argument, the filename we want to calculate the md5 hash.
os.Open(filename) tries to open the file, os.Open(..) returns a pointer to the file named fileand and err , if err has content (err != nil) means that there was an error and file is not valid.
defer file.Close() instructs go to close the file as last thing to do before program exits and only if the file has been opened successfully.
Calculating the hash
This part of code calculates the md5 hash of the file
hash := md5.New()
if _,err := io.Copy(hash, file); err != nil {
fmt.Println(err)
return
}
sum := hash.Sum(nil)
fmt.Printf("MD5 (%s) = %x\n",filename,sum)hash := md5.New() this returns a struct pointer with callable functions, will be used to to calculations.
io.Copy(hash, file) streams file bytes to hash.
sum := hash.Sum(nil) calculates the md5 hash, nil is needed to perform plain calculation of md5
fmt.Printf(“MD5 (%s) = %x\n”,filename,sum) prints the filename and the hash value in hex.
How to compile and run the program
i have named my program as md5sum.go to compile it enter
go build md5sum.goif nothing goes wrong you should see an executable in the same folder
Running the program
To run the compiled program enter the following, this will calculate the md5 hash of your source code.
md5sum md5sum.go
MD5 (md5sum.go) = df57ba9b7e153bc496a06dbabeea0f4fTo run the program without compiling you can do the following
go run md5sum.go <filename>Conclusion
In this very first version we saw how we can create a very simple Go program that calculates the hash of a file, in the next version we will add the option to read file contents from STDIN, which can be very useful when used with other scripts or in cases we want to calculate md5 hash of a string and not a file.