Go (or Golang) is an open-source programming language originally created by Google that has been gaining in popularity due its high performance, expressiveness and readability. This blog post will describe the Go programming language’s origins, main features, and advantages for programmers and businesses. At the end of the article, you will find the use cases where Golang works best.
What the Golang was created for?
When Google was growing exponentially, it had to deal with problems of scale. They simply had lots of everything: tens of thousands of engineers, lots of software and systems, millions of lines of code (especially behind their network servers) being developed by hundreds of programmers, and finally lots of hardware on which all this software was launched. To make matters even more complicated, the entire source code was stored in a single monolithic repository. While the code was being built, it was essential to verify if the changes introduced in one place didn’t result in other components not working properly. A huge amount of time was needed to build such a vast codebase. To perform such a build, Google created its own build system to compile the code on many machines in parallel.
Yet, despite this and many other optimization efforts, the time needed to build certain systems reached several dozen minutes in 2007. Given the enormous scale, developing software was a slow and difficult process. Code compilation (mainly in C++) lasted too long. On the other hand, using threads and memory sharing in C++ and Java to write concurrent code was too complicated. Programmers made a lot of mistakes, and the code was often not optimized. To use concurrent programming, a programmer had to create many threads that shared memory of the same process. If there were too many operations waiting for external resources (disk, network, etc.), as was often the case in a typical network application, a thread was left waiting—and gobbling up resources like RAM and CPUs (for context switching). If a server was processing 10,000 parallel connections, the program became very resource-hungry.
To solve this problem, alternative models of concurrent programming were created. An asynchronous model used especially in Node.js is one of them. In this model, when a function is about to perform an I/O operation, it does not block thread, thus making the entire process more effective. Still, it is more complex for programmers to use and much more difficult to debug.
Additionally, there were many approaches to C++ programming, but none emerged as best-in-class. Java faced the same problem. As a result, code written by one programmer was difficult for others to understand. Finally, managing dependencies in a program was problematic. It was particularly hard in C++ to say what functionalities were actually used in the program code, as this language allows you to use a certain functionality without including it explicitly in the code. Consequently, programmers did not actually know what was being used in the program and what could be removed. This resulted in the code being difficult to manage and in needlessly long compilation times.
Fed up with these pitfalls, Googlers Robert Griesemer, Rob Pike and Ken Thompson created a new language that would increase the productivity of Google engineers and allow them to use the company’s huge hardware resources more effectively (CPUs with many cores, a fast network and huge clusters for data processing). Since the most widely used programming languages at Google were C++ (mainly for servers) and Java/Python (the rest of the code), this new language needed to be similar to them, so that programmers could learn it easily. Moreover, many college and university graduates in the US already knew C and Java, so it would also be easy for them to learn.
Golang’s creators sought to create a statically typed compiled language which would be as easy to use as dynamically typed languages and have a similar level of expressiveness (i.e. conciseness as represented by the number of code lines needed to express a given concept). In other words, they wanted to combine C++ with Java and Python while capturing the best features from all of them. As a result, Golang has elements from both statically and dynamically typed languages.
The statically typed language features include:
- type safety—incorrect type use errors are signalled during compilation, rather than when running the code; thus it is possible to avoid part of the problem in the production environment and perform code refactoring safely,
- high performance.
The dynamically typed and interpreted language features include:
- the ability to run the code quickly.
Not revolutionary, Golang simply combines different features borrowed from CSP (Communicating Sequential Processes) and other programming languages like Java, Pascal. It doesn’t introduce any particularly new or revolutionary functionalities à la Rust, but it does take what is best from other languages and uses it for purposes more pragmatic than academic. You can check our article about using Go or Rust for projects.
Minimalist and simple syntax
Golang syntax was designed to allow virtually everything to be programmed using minimal syntax. And though the language has been on the market for a full ten years, its creators have not introduced any serious syntax modifications in order not to make the code overcomplicated.
This approach stands out from those employed by other mainstream languages, especially C++ and Java. Their syntax has been considerably expanded over the years to keep up with the newest programming trends and introduce features programmers sought to have. As a result, today these languages are completely different from their original versions.
Thanks to the lack of changes in Go, programs being written today in this language differ little if at all from those written a couple of years ago. Go programmers do not have to learn new syntax or new paradigms, as Golang’ syntax is still the same and still as easy to learn as ever.
More importantly still, a simple syntax limits the number of ways code can be written by programmers. As a result, the code authored by different programmers looks alike and is easy to read and understand.
Key features of the Go language
The code can be run quickly. Until now, this was a feature strictly of interpreted languages. Still, Go needs a compiler to compile code to a machine language. Nevertheless, this compilation is very fast, because the language was designed to enable its compiler to analyze dependencies quickly and avoid loading files repeatedly. This is why programs written in C were compiled so slowly. Go, on the other hand, compiles the source code incrementally, creating an object file for every package. When somebody uses a given package, it loads only the previously prepared file. This significantly decreases the number of read operations on the hard drive.
Unit tests can be launched very quickly. Since Golang knows the dependencies of the given package, it needn’t be recompiled, as long as the dependencies haven’t been changed. As Go also caches the test results, there is no need to launch tests for package code that has not been actually recompiled. The test result will be returned from the cache. This allows unit tests to be launched very quickly, as they will include only code that has been changed.
Programs written in Go are executed fast and use little RAM. When Go code is compiled, an executable file is created. This is not a bytecode or any other intermediary code, but a machine code.
Programmers don’t have to worry about memory management. Golang has a built-in garbage collector which removes from the memory instances that are no longer being used. Additionally, the Go compiler uses escape analysis algorithms to decide what memory type (stack or heap) should be allocated to a given structure. A programmer does not have to worry about it. This feature makes programming much easier, while at the same time boosting software performance considerably.
Which well-known companies use Golang in their projects? Read the article to find out the answer, and check what else you should know about the Go programming language.
Golang vs other languages
Go vs Python
Go and Python have a lot of differences when it comes to their features. There are differences in their readability, speed error management, libraries and many more. For example, they both support concurrency, but Go does so in a much more user-friendly way than Python. Python also doesn’t require specification of the types of arguments passed to functions. This can cause issues when arguments are not clearly described and someone using that function doesn’t know what they mean. This is why Python functions require proper documentation. There is no such issue in Go - the headlines of the function show you which types of arguments can be used.
A significant difference between Go and Python is that Go is a compiled language, whereas Python is an interpreted one. That makes Go’s performance significantly faster than Python’s.
A similarity between these two languages is their minimal syntax - both are easy to understand and learn.
Go vs C++
Both Go and C++ have their advantages and disadvantages, so choosing between them requires a fair deal of consideration and taking a lot of aspects into account. C++ is a general-purpose, object-oriented computer language. The Go programming language is built around simplicity and scalability, also defined as a simpler and more compact, procedural, and concurrent language. C++ on the other hand, is an object-oriented, procedural, functional, and general-purpose mid-level language. C++ syntax has expanded over the years, and nowadays the language is completely different from its original version.
Concurrent programming made easy
Many years ago, when C++ and Java were born, threads were commonly used in concurrent programming. Threads are abstracts allowing a programmer to write concurrent code. Each thread did only one thing at a time. If a programmer wanted a program to perform many functions, they simply created multiple threads, which communicated with each other by sharing the memory inside the process. Access to this memory was synchronized with synchronization primitives. The code in a single thread was executed sequentially. This model was simple and easy to implement.
The rub lay in sharing the memory, which caused multiple problems that gummed up implementation and generated countless bugs that were detected only during production. Additionally, this model was never effective when it comes to using hardware resources. For example, if there were more than 1000 threads, switching threads gobbled up a considerable share of RAM.
Go introduced an alternative model of concurrent programming, one based mainly on CSP language. This new model has two important advantages over the thread and memory sharing model. First, goroutines are used instead of threads. They significantly decrease hardware resource usage. Tens of thousands of goroutines working simultaneously is standard in many Go applications.
Secondly, goroutines communicate with each other using channels that can be described as a mailbox of sorts. One goroutine can send messages to another using the channel. This makes it much easier to understand such code, as there is only one point of communication between the goroutines.
Why use Golang
Go allows you to use different programming paradigms:
- imperative—a programmer gives step-by-step instructions to the machine what actions a program is to perform,
- functional (support for closures)—a programmer can change a programs behavior by providing code as closures,
- procedural—in order not to repeat code, a programmer can create reusable code pieces like procedures and run them multiple times in a program,
- composition (over inheritance)—simple (often one-method) Go interfaces help developers set clear and comprehensible boundaries between components.
It is the programmer who decides which paradigm to use. For small programs, the procedural approach may be the best, while for more complex systems, object-oriented programming becomes a must.
Golang has excellent team scalability. It can be used both by small teams of programmers and in large enterprises. This is especially useful when you do not know how your team’s composition will change in the future. Python, Ruby and other dynamically typed languages, on the other hand, are an ideal choice for a team of one or two programmers, as these languages provide instant feedback. With code developed for months and years by a much bigger team, using dynamically typed languages effectively becomes a challenge—one Golang is eminently qualified to solve.
You can use Golang both for high- and low-level programming. You can achieve abstractions and polymorphism. You can also employ proper code refactorization to optimize memory layout for data structures and influence where a compiler will allocate the structure. You can use high-level channels, but when high performance is crucial you can also use mutexes.
Because there is no compiler launched on the program run (JIT), compiled code is foreseeable. This feature makes Golang particularly useful for writing high-performance systems that also contain complex logic. If you want to be clear, you can use i.a. encapsulation. In other places, you can use many optimizations. This is the case of database systems, middleware software and infrastructure of any kind. Golang was used in such projects as Kubernetes, Docker, Prometheus or M3.
Golang is a perfect language to code network servers, especially web servers and microservices. Go has functions to support network programming already built into the standard library. You do not need to use frameworks to create simple REST applications (similarly as in the case of NodeJS). In case of more complex ones, you can use advanced HTT