GoLang, The Next Language to Learn for Developers
The Origin Story
Rumor has it that GoLang’s ideation occurred during the lull in which developers were waiting for their program to compile. These devs were getting tired of waiting, and not working. Three programmers at Google, rose to the occasion as they have so many times before. In 2009 Go was announced, and version 1.0 was released in 2012. Three engineers at Google (Robert Griesemer, Ken Thompson, and Rob Pike) created a systems level language to replace all of the other ones since there hadn’t been a new one in that arena in a while and none of the existing languages were considering multi-threading as a core tenant.
These three worked on some pretty big deal projects in the past. That includes the C programming language, Unix, UTF-8, JVM, and a couple others. Go is the first language in a while where modern-day engineers are given the ability to not have either efficient compilation, efficient execution, or ease of programming. All three were not all available in the same mainstream programming language. Go is an attempt to bring all of these capabilities into one language.
What Does Go do at Google?
Well, Go is specifically a systems-level programming language for large, distributed systems and highly-scalable network servers. It is meant to replace C++ and Java in terms of Google’s needs. Go was meant to alleviate some of the slowness and clumsiness of development of very large software systems. To be a little more specific, Go helps solve …
- slow compilation and slow execution
- programmers that collaborate using different subsets of languages
- readability and documentation
- language consistency
- versioning issues
- multi-language builds
- dependencies being hard to maintain
Don’t Take My Word for it
Go has climbed the ranks on StackOverflow to the fifth most ‘loved’ language. The developer survey shows that currently 65.6% of developers that are using Go, will continue to work in Go rather than any other language if given the choice.
Go is also one of the fastest growing languages on Github, Go is CRUSHING it. In 2016, Go had around 188k opened pull requests, which was up 93% from the previous year. In 2017, it jumped to 285k to become the 9th most popular language on Github.
Go has become the ‘next language to learn’ for a lot of developers. HackerRank surveyed exactly that, and Go is taking a significant lead. This assessment was from February of this year.
Obviously, carrying Google’s name has applied a serious multiplier on Go’s success and adoption. You’re interested now, right? Well assuming you weren’t before you decided to click on an article about GoLang…
How is a System Level Language That Popular?
Simplicity is probably one of the greater reasons why Go has been adopted so easily. When you look at all of the other languages and their evolution, they are constantly introducing new features which sounds like a good thing, and it is, don’t get me wrong. The outstanding issue is that said languages are becoming more and more similar in functionality, look, and feel. Go is what it is, and doesn’t try to be much else. It covers its own bases very well but doesn’t stretch itself too thin. This was completely intentional. The contract* that the three developers decided on was that all three of them must agree on a feature and that it was the right feature to be included in Go. This was meant to assure that Go had the simplicity and readability that Rob, Robert, and Ken all decided was absolutely critical. The current idea with Go is that there won’t be significant changes in Go’s functionality or aesthetic in the long term. The only suggested feature that the developers are even considering adding is generics. The languages FAQs document mentions that generics may be added at some point, but they just don’t feel the urgency. There may be a Go 2 eventually, but probably not for a few years.
Why so GOpinionated?
The Go team had come to the conclusion that with adding more features and more functionality, there comes greater complexity and more difficulty in ramping up new developers on projects, and in learning the language in the first place to begin writing production-ready code. Go is meant for any developer to be able to begin writing production-ready code almost on day one.
Concurrency is NOT Parallelism
It is important to explain that concurrency is not inherently parallelism. Concurrency is a much more structured approach for dealing with many processes, rather than doing a bunch of things (or many instances of the same thing) at the same time. So being concurrent doesn’t mean that two processes will never run at the same time. That will occur, but it is more about the communication of said processes. Knowing when to do something, and how to do it as well. So with Go, they are meant to talk. Though you can create parallelism, that isn’t really the whole picture.
To help better explain that idea, imagine (in the spirit of the World Cup finishing up recently) a soccer team during the game. Each player on that field is a single process (GoRoutine in this situation). They are all running and communicating with the ball (data) being their trigger or point of communication. The goalie is not always moving, but acts accordingly when the ball is somewhere within their half of the field, and DEFINITELY when it is near the box. Every player (GoRoutine) has a job to do that is independent, but coordinated with the others. If we were talking purely about parallelism, each player would be playing a game all by themselves with no interest in what any of the other players were doing.
Go’s solutions for concurrency:
A GoRoutine in the Go programming language is a lightweight thread that is managed by Go runtime. If you just put ‘go’ before a function, it means that it will execute concurrently with the rest of the code.
Channels are pipes that connect concurrent GoRoutines. You are able to send values and signals over Channels from GoRoutine to GoRoutine. This allows for synchronizing execution.
The Select statement in Go lets you wait and watch multiple operations on a channel. Combining GoRoutines and channels will show off the true power of concurrency in Go.
What’s unique about Go?
- Go has implemented latency free garbage collection and fast compile times. The language completely (and I mean completely) abstracts away garbage collection and manual memory management. Both of which are a massive time suck when implementing manually in the likes of C and C++
- There aren’t really classes in Go. Rather your structs and interfaces are all typed. The following is a very simple example of both.
- Go is statically typed, and because of this, most (if not all) errors are caught in compile time, rather than runtime. Go is type-safe, meaning that you can’t mess around with types in a way that would crash the program. Go is also memory-safe, meaning that you won’t have to deal with memory vulnerabilities like buffer overflows and dangling pointers.
- In many other programming languages, you would have to choose to either throw/return an exception/error, but because you can return tuples in Go, you can both throw an error and return a value when necessary. This is important because Go doesn’t have exceptions. Go relies on ‘if’ing for errors. It is up to you to handle it how you’d prefer. This may sound like a limitation, but it can be quite freeing and powerful in the right situations.
- Functions can be passed into other functions, returned, and declared as variables. Functions can also be created within other functions, also called closures.
- Go has a defer keyword that allows for Deferring functionality. What that means exactly is that you set some action or execution to be deferred until the surrounding function returns. Deferred calls are evaluated immediately wherever they are, but will not execute until said surrounding function is completed. Also, deferred function calls are executed in last in first out order.
There are more unique things about GoLang, but that was just a quick once over for cool stuff.
MY PROGRAMMING LANGUAGE IS BETTER THAN YOURS
C and C++
Rust and Go were compared because they were both systems level languages that came out around the same time and aim to solve issues that the other doesn’t. Rust was meant to be completely interoperable with C and D. Go wasn’t.
Go can be interoperable with these. There are two Go compiler implementations, gc, and gccgo. Gc uses a different calling convention and linker and because of this, can only be linked with C programs following the same convention. Gccgo is a GCC frontend that can be linked with GCC-compiled C or C++ programs. Gccgo is slower to compile than the default gc, but supports more powerful optimizations so many programs compiled with it will run faster. This takes great care and even more patience.
The cgo program provides the mechanism for a foreign function interface to allow safe calling of C libraries from Go code. SWIG extends this capability to C++ libraries.
Simply stated, Go is meant to be a standalone maintainable and efficient language, and Rust pretty much just gives C devs a new way to code that is easier and faster than C (but what isn’t).
Java and Go will obviously be compared, but they have a crazy amount of differences. Java is much more expansive, has frameworks out the wazzoo, and has had a chokehold on the industry for years. Since there are plenty of reasons why to use Java, I will instead mention the reasons Go is better. Please keep in mind that Go isn’t meant to completely replace, but to improve in the areas that it is meant to improve.
- Because of hierarchy and polymorphism, Java projects become pretty hard to maintain. Interfaces, which are supported by both Go and Java, can do pretty much the same thing, but Go’s interface is more flexible.
- JVM is (obviously) a virtual machine by name, where Go compiled binaries run natively/directly on the processor.
- Java doesn’t implement anything similar to goroutines in the standard library. There are libraries that solve that issue, but even still, they are relatively hard to maintain, but Go comes with phenomenal concurrency out of the box.
- Go has an arguably faster development cycle once the development team has learned the language.
Python and Ruby?
An unexpected comparison is that Go has been considered as a replacement or supplemental language to the likes of Python and Ruby.
It has replaced Ruby when high scale performance is necessary. Go is also able to interact with almost all databases as a server-side language, whereas Ruby has limited compatibility to only be able to use the most popular databases.
I’ve read about many Python programmers deciding to switch to Go in enough cases that there is a plethora of talks on youtube, blog postings, and side by side code comparisons of Python and Go. People have been using Go to write scripts even though it isn’t a scripting language.
Which language is considered one of the greatest competitors to Go? Well, it is actually Node.js because Node solves “high concurrency of HTTP requests, and high volume reads and writes to databases”. GoLang just does quite a bit better.
I would suggest checking out Hackernoon’s article, that shows a real-world example of why you would use GoLang in place of Node.js with and AWS Lambda function built in the two respective languages, and then load testing them.
I’ve talked plenty about why and how Go is great, but it has some downsides. These downsides should for the most part be irrelevant if you are using Go for what it is intended for, because it just wasn’t meant to do many of these things on purpose. Go does what it does REALLY well. It’s fast, pretty easy to learn, and highly scalable. BUT it does have significant limitations when it comes to things that it obviously can’t do, but I must say that’s mostly developer opinion. Use the right tool for the right job.
- There isn’t much attention given to version maintenance of packages that you ‘go get’ and it is suggested that if you think that a future version will cause issues that you store the needed versioned package, locally or included it in your repo. (there are solutions for that. See dep)
- No Generics, no .map, .reduce, .filter
- No exceptions or assertions, as mentioned earlier (but I feel that this could go either way)
- No Ternary operations. Use the good ole ‘if else’ statements.
- Absolutely no tolerance for unused variables or imports (but is that really a bad thing?)
- Your virus protection might think your compiled binaries are infected because it doesn’t understand the structure of a Go Binary 😅
- No pointer arithmetic (but thats for safety, and simplifies implementation of the garbage collector)
- And honestly, dealing with GOPATH is kinda messy and annoying. You are forced to do all of your go projects within your GOPATH, but IDE’s like VSCode and GoLand allow you to set the GoPath for your project without affecting your system’s actual GOPATH.
Its popularity is growing at an increasing rate, and if you’re getting into the serverless and cloud game, I’d consider it crucial to learn GoLang. With the speed advantages of compilation and execution, your efficiency and cost of execution is positively impacted to say the least. It has become a critical component of cloud infrastructure and probably not going anywhere for quite some time.