The coolest things about Go Language

Alejandro Lampropulos
Worldsensing TechBlog
5 min readOct 1, 2020

Introduction

Go is a relatively new language, created by Robert Griesemer, Rob Pike, and Ken Thompson at Google by 2009. It is open source, so anybody can contribute to it and propose new features.

It appeared mainly to make Google’s software engineers lives easier, as an alternative to C. It is targeted to systems programming, such as cloud systems, distributed systems and microservices.

A few characteristics

Go is statically typed. All variables need to be declared with a given type. The bool, string and “number” (int, uint, float64, complex128, etc) types are the basic ones. Then, structs (just as in C) can be declared too. This is good to detect errors at compile time. Oh, BTW, Go is a compiled language.

Go code is compiled very fast! This is one of the key aspects that the creators tried to improve regarding C and C++, and they did. Moreover, the execution time is really fast, as the code is compiled directly to machine code. This also makes the executable highly portable to other machines with the same platform.

Go has interfaces. For Object Oriented programmers, this may be a little disappointing, but Go does not have classes. It does not support inheritance. However, it does support the creation of structs and the definition of methods for them. Furthermore, it supports the definition of interfaces, which enable loosely coupled systems. And another cool thing is that you can define an empty interface (interface{}) and you will declare a generic object!

Go focuses on handling errors. Go does not support exceptions. Its philosophy is that a function must return the return value (or values, as it can return several variables at the same time) along with an error value. This makes developers think about what to do when there is a failure. Nevertheless, there is something similar to exceptions, which are the “panic” and “recover” mechanisms.

Go has garbage collection. This is a great improvement to C and C++. It is a very efficient language, which adds this highly useful feature that most of the recent languages do.

Go supports built-in concurrency. This is by far the coolest feature of Go Language! It is very efficient and easy to use. We will explain it in detail in the next section.

Concurrency in Go

Firstly, let’s make the difference between concurrency and parallelism. Concurrency is about independent processes executing at the same time but not necessarily simultaneously. Parallelism implies that the execution is simultaneous. Parallelism, then, can only be achieved with multiple cores, while concurrency can be done at one core only, by scheduling the different processes correctly. Go implements very efficient concurrency and it also supports parallelism.

Go is thought to follow the actor model for its concurrency. In this model, an actor is the primitive unit of computation. It’s the thing that receives a message and does some kind of computation based on it. They get an input, perform operations and provide an output. The actors in Go are the goroutines.

Actors are completely isolated from each other. This means that they do not share memory but they communicate through other structures, which provide them with synchronization. Go implements channels for this purpose. Even if the use of shared memory structures is possible through different goroutines, the use of channels makes the concurrency really easy and safe.

The best part is that goroutines are very lightweight. Go schedules the execution of goroutines over system threads, allowing multiple of them to run concurrently on a single OS thread. The benefits are the reduced stack of the routines (4KB compared to 1MB for an OS thread) and the saved cost of context switches among OS threads, which is a lot larger than switching among goroutines. We could have even hundreds of thousands of goroutines running concurrently at a very low cost!

We have also mentioned that it is easy to use concurrency in go. Let’s look at an example!

package mainimport “fmt”func add_string(string_to_add string, input_ch chan string, output_ch chan string) {  fmt.Println(“Running: add_string”)  result_string := <-input_ch + string_to_add  output_ch <- result_string}func initialize_string(initial_string string, input_ch chan string) {  fmt.Println(“Running: initialize_string”)  input_ch <- initial_string}func main() {  input_ch := make(chan string)  output_ch := make(chan string)  go add_string(“Hello World!”, input_ch, output_ch)  go initialize_string(“”, input_ch)  fmt.Println(“Waiting for goroutines”)  fmt.Println(<-output_ch)}

And after running this code, the output is:

Waiting for goroutinesRunning: initialize_stringRunning: add_stringHello World!

So here we see how easy it is to run a concurrent go routine. Just define a function and add “go” before you call it. As simple as it gets! This will schedule the goroutine but the execution of the caller function will continue. In this case, we call the function to add the “Hello World!” first. Then the initialization function and then we print the message “Waiting for goroutines”, but the console shows a different order to print the messages. Why?

As we mentioned, in order to synchronize the goroutines, we can use channels. We start by creating an input channel and an output channel and then we use them in the following way. The add_string function waits until there is something in the input channel. Then we call the function to initialize the input channel with an empty string. However, the main function continues its execution and prints “Waiting for goroutines”. Then, it waits for the output channel to have something in it. This will allow the initialization function to put the empty string to the input channel. The add_string function will wake up and add “Hello World!” to the output channel and then the main function will wake up again and end up printing the complete message in the end. Easy, right?

Where is Go used?

Go is used to develop many solutions that you may know, like Google, YouTube, Soundcloud, Docker, etc. However, the one that made us in Worldsensing start learning about Go was Chirpstack. This is an open-source LoRaWAN network server stack. It provides a web-interface for device management and many ways to integrate other applications, such as APIs, MQTT queues, etc. It has a modular architecture, as you can see.

Chirpstack is configurable and easy to deploy. You can even find an open-source project with a docker-compose.yml file that starts everything very easily!

As you can see, cool languages like Go allow developers to create cool projects.

References

https://www.golangprograms.com/go-language.html

https://hackernoon.com/the-beauty-of-go-98057e3f0a7d

https://www.brianstorti.com/the-actor-model/

https://medium.com/swift-india/concurrency-parallelism-threads-processes-async-and-sync-related-39fd951bc61d

https://www.chirpstack.io/

--

--

Alejandro Lampropulos
Worldsensing TechBlog

Embedded and Cloud Software Engineer / Team Lead / Engineering Manager