I love the Go programming language, or as some refer to it, Golang. It’s simple and it’s great.
I write this on a tangent. Didn’t expect Golang to be so good.
I first picked up go around January 2016, it had a relative small but enthusiastic community here in Israel.
I didn’t think much of it at the time, I was honing my programming skills and Golang was just a tool I’ve used to accomplish a task.
Even one year ago, using go was brilliant. The process was straightforward once I’ve got the general hang of the language.
I wrote a crucial piece of code for Visualead, the company I work for, and it didn’t let us down, still running in production a year later with zero maintenance since then.
Recently I found myself again using Golang again, and I felt compelled to write about the reasons I fell in love with Golang.
This is one of the first things you’ll have to handle once you begin writing in Go.
Setup your GOPATH directory anywhere on your computer, complete with bin, src, and pkg directories and you are ready to begin writing.
// How the directory structure looks like:
go
- bin
- pkg
- src
Under my home directory I create a new directory for every programming language I write in. My user home directory is filled with folders like these:
chef
cpp
elixir
elm
go
javascript
meteor
ocaml
php
python
scala
None of these languages enforce this structure besides Go. Go forces you to define a root directory for all of your Golang goodies, and it does it for a good reasons which are coming right up.
Want to create a new Golang applications? Simple.
Go to your $GOPATH/src directory, create a new folder, create a new file.go , call the package main , add a func main() {} function and that’s it. all of the Go goodies are available to you since that moment forward.
More on Go goodies coming up! but first a few words about the Golang modules.
My favorite programming paradigm done right. I see the module system as a sort of alternative to the Object Oriented classes system.
Golang calls it’s modules packages. So from now on everytime we say a module we mean a package and vise-versa.
Module == Package == Module
In Golang every directory you create becomes a package. A package can become an application if it’s name is main.This is helps with a natural separation of code into manageable logical chunks.
You always want your business logic to be created from reusable components, or packages in case of Golang.
In my current app I have to manipulate some lines in some files, and upload them to AWS S3 once i’m done.
My app structure looks like this:
src
- my_app
- - main.go
- - main_test.go
- - uploader
- - - uploader.go
- - - uploader_test.go
- - replace_file_lines
- - - replace.go
- - - replace_test.go
- - - strings_util.go
- - - strings_util_test.go
The _test.go files are of course the way to do unit test files for Golang, which has a testing framework built in it’s core.
Also to those who are coming from an object oriented language, it helps to think that every directory here is a complete static class, and every function or variable inside the .go files becomes it either a property or method.
Here’s a possible example of how replace.go can look like:
<a href="https://medium.com/media/5fd49f65bc6cc1843e6727541a244ae3/href">https://medium.com/media/5fd49f65bc6cc1843e6727541a244ae3/href</a>
If a directory shares more than one .go file, all the methods and variables are shared between the entire package, even the private ones. It helps for separating a package into even smaller chunks and avoiding large single files.
Without going into Object Oriented vs Functional/Procedural, it’s just important to know that the Go creators decided to not include classic classes it the language. Instead opted to use structs/interfaces, and packages of course.
Golang has a convention of how everything is supposed to look, the exact spacing which is needed in each case and each line.
This allows developers to focus on writing code instead waging wars about curly braces locations.
The old {} vs { \n } war:
Or perhaps I am only happy because my side won in Go?
Read more about it here: https://golang.org/cmd/gofmt/
imports are always relative to GOPATH/src . Always. I cannot overstate how much this decisions saves me in frustration.
Warning: the next line is confusing by intention.
When working with other languages you either can use relative/absolute imports, or somehow set a weird import that will allow you to import a file from whoknowswhere location ( I am looking at you Python ).
Go solves it in a unique way. All imports, no matter in which file, will always be relative to GOPATH/src
So in case of my_app, it’s main imports will look like this:
<a href="https://medium.com/media/b25aa90e6c930bda3804c3c39789491b/href">https://medium.com/media/b25aa90e6c930bda3804c3c39789491b/href</a>
my_app is under src, so we need to mention it first, then we import the packages that exist under my_app , like uploader and replace_file_lines . Notice we are not importing single files, but instead whole packages. Works like a charm and causes ZERO confusion.
Furthermore, Golang won’t compile unless you actually use the packages you import, this tiny feature helps you to know that every import is actually used.
Expecting your programmers to write a clean code without unused imports? why won’t you let your local Gopher take care of that?
The import sections leads us to the next great feature of Golang, the go get feature. While others are impressed with JavaScripts NPM package manager, Go just uses any git repository as it’s package manager.
How does it work?
I’ve wrote before that I needed to upload to S3 right? well then that means I need to AWS SDK to accomplish that.
To make this work, I just open my terminal and write:
go get github.com/aws/aws-sdk-go
What’s going on here? Nothing special, Golang just downloads the repo from https://github.com/aws/aws-sdk-go into your GOPATH/src directory.
Then all you have to do to use the aws-sdk is just import it:
<a href="https://medium.com/media/7265ea218a520ebb4556006a37fe241f/href">https://medium.com/media/7265ea218a520ebb4556006a37fe241f/href</a>
Remember that all imports are relative to the GOPATH/src ? From that you can understand that the s3 package for example resides now under GOPATH/src/github.com/aws/aws-sdk-go/services/s3 .
Simple. Elegant. Another star for the Gopher.
We’ve been focusing so far on GOPATH/src but there are still other directories we need to address, GOPATH/pkg and GOPATH/bin .
Golang is a compiled language, it means that the code has to be compiled in order to run. Golang is compiled fast. How does it work?
Everytime your compile your code to run it, Golang creates a .a file in the same path as your package, only under the GOPATH/pkg directory. It means that if you compiled the aws-sdk for example. It’ll be compiled once, and shared between all of your other code.
Of course this is not the only reason Golang compiles fast, but it’s just an intro that helps you to understand the role of GOPATH/pkg
Now, what about GOPATH/bin ? When you run the go install command, go creates a binary file, and places it under GOPATH/bin , the file gets the name of your main package’s directory my-app in our case.
Why is it so great? Well you can add GOPATH/bin into your global PATH variable, and all binaries your build are available in your command line, without you doing any extra work! ( Isn’t it great :D ? )
Deploying to other distributions instead of the one you are writing your code on? Well don’t worry, you don’t need to have a windows machine to build your code for windows. Golang got you covered.
Just run:
GOOS=windows GOARCH=amd64 go install
And our code will output a binary ready to deploy on a windows machine. The .exe file will appear at GOPATH/bin/windows_amd64/my_app.exe . Like a walk in the park.
Golang is aimed to be a simple language.
I love the following post asking why Go wasn’t designed to be a functional language: https://www.quora.com/Why-wasnt-Go-written-as-a-functional-language
“Programmers working at Google are early in their careers and are most familiar with procedural languages, particularly from the C family. The need to get programmers productive quickly in a new language means that the language cannot be too radical”
And simple it is.
Here’s a list of some features Golang doesn’t support:
While sometimes I find myself missing language features when writing in Go, I can always do everything that I want. Just sometimes it requires more writing and sometimes thinking. The bottom line is, it leads to code which is easier to reason with because it’s less abstract.
It sometimes amazes me how fast I can achieve a goal when writing in Go, without having years of experience, just because the language is so accommodating and clear.
I have left the concurrency talk by intention to be last. Why? because I don’t think it’s so important.
It’s an amazing feature of the language. But sometimes it’s presented as the essence of Go, which I believe it is not.
Therefore let me try to sum it up in one paragraph.
Yeah, Golang has great concurrency. You don’t deal with threads but rather create cheap goroutines which are simple to make and manage. Goroutines allow you to distribute the load across all of your CPUs without worrying on how to manage it all.
Still interested in understanding goroutines? Read about them here: https://tour.golang.org/concurrency/1
Did I mention I am a Functional Programming enthusiast? Then why I am so attracted to Golang? it doesn’t even have a concept for mondas. Who knows… The universe works in mysterious ways.