DEV Community

Cover image for Go: The Language That Just Works
MEROLINE LIZLENT
MEROLINE LIZLENT

Posted on

Go: The Language That Just Works

Three engineers, Robert Griesemer, Rob Pike, and Ken Thompson, at Google in 2007 were tired.Three engineers at Google, Robert Griesemer, Rob Pike, and Ken Thompson were tired in 2007. Annoyed with waiting for C++ code to compile. Frustrated with the messiness that seeped into big code bases. Frustrated by the limitations of languages on their size and concurrency requirements of today's infrastructure.

So they built their own.

This is the bold idea that was born of Go: What if there was a language as fast as C, as readable as Python, and as concurrent as possible from the ground up? It was released as open source in 2009 and version 1.0 came in 2012 and has become one of the most impactful programming languages of the last 20 years.

Go's goal is to "provide for something that is easy to program but also efficient and safe like a statically typed, compiled language.

Go by the numbers

  • #8 on the TIOBE Index (2024), up from #14 in 2020
  • According to the Stack Overflow 2023 Developer Report, 13% of developers use Go on a regular basis.
  • Average salary is 70% higher than average Go developer salary.Median salary is 70% higher than the average Go developer's salary.

What makes Go genuinely different

Go is not just another C-family language. It involves a series of conscious and subjective decisions all of which are required to create something unusual: a language that can be used for small projects as well as infrastructure for the planet and remains the same in your head.

1. Concurrency as a first-class citizen

The Go runtime manages lightweight threads called goroutines. Conventional OS threads take 1MB+ per thread. Goroutines are born small, at just 2-8 KB — and can be started as needed; 100,000s can run on a single machine concurrently.

package main

import (
    "fmt"
    "sync"
)

// Fan-out: distribute work across goroutines
func processJobs(jobs <-chan string, wg *sync.WaitGroup) {
    defer wg.Done()
    for job := range jobs {
        fmt.Printf("Processing: %s\n", job)
    }
}

func main() {
    jobs := make(chan string, 100)
    var wg sync.WaitGroup

    // Spin up 10 workers — goroutines are cheap
    for i := 0; i < 10; i++ {
        wg.Add(1)
        go processJobs(jobs, &wg)
    }

    jobs <- "build Docker image"
    jobs <- "run test suite"
    jobs <- "deploy to staging"
    close(jobs)

    wg.Wait()
}
Enter fullscreen mode Exit fullscreen mode

Concurrent programs are easier to reason about and are much less prone to race conditions with the CSP (Communicating Sequential Processes) model, which is the model in which goroutines communicate through channels and not memory.

2. Blazing fast compilation

Go can take seconds to compile large codebases, instead of minutes. This isn't just a little convenience, this actually alters the way development feels. You have a very close feedback loop, no matter what the scale is. A Go build with over a thousand files, and it takes 3 seconds, is something of a miracle.

3. Static typing with type inference

The static type is able to detect bugs at compile-time, while the shorthand syntax := and interfaces make the code feel light.

// Explicit type declaration
var name string = "Gopher"

// Type inference — Go figures it out
name := "Gopher"

// Interfaces are satisfied implicitly (no 'implements' keyword)
type Writer interface {
    Write(p []byte) (n int, err error)
}
Enter fullscreen mode Exit fullscreen mode

4. Garbage collected with low latency

Go's GC is optimized for latency operations. Modern versions are able to deliver sub-millisecond GC pauses (i.e. makes Java real-time systems feasible where it would have been a deal-breaker).

5. Batteries-included standard library

Go ships with an exceptionally rich standard library covering:

  • HTTP servers and clients (net/http)
  • JSON encoding/decoding (encoding/json)
  • Cryptography (crypto/tls, crypto/sha256)
  • Testing framework (testing)
  • Database interfaces (database/sql)
  • Templating (html/template, text/template)

All production-quality.
All without installing anything.

6. Single static binary output

Write-once-run-anywhere. Go generates a single binary file that can be executed without relying on any external runtimes. The deployment is just a copy of one file. The images of the containers shrink from gigabytes to megabytes.

# Cross-compile for Linux from macOS
GOOS=linux GOARCH=amd64 go build -o ./bin/myapp .

# Your entire app: one file
scp ./bin/myapp user@server:/opt/myapp
Enter fullscreen mode Exit fullscreen mode

7. Enforced formatting

Your code is automatically formatted by gofmt. There is one style for all Go code, everywhere, all the time. No bikeshedding in PRs, no tab vs space debates, no style guide debates. The point of code reviews is logic and not looks.

8. Explicit error handling

Go treats errors as values, not exceptions. Every function returns an error that you must consciously handle.

file, err := os.Open("data.json")
if err != nil {
    return fmt.Errorf("opening data file: %w", err)
}
defer file.Close()
Enter fullscreen mode Exit fullscreen mode

This is an interesting experience for developers coming from Python or JavaScript. It will be useful over time; in Go code bases, the failure modes will always be obvious in code. No unexpected path which catches you off guard in production.

Where Go dominates today

Go has not attempted to be all things to all people. It made deep inroads in certain areas of specialization and those areas happen to be the backbone of modern computing.

Go is the home of cloud infrastructure. The tools that power the internet are filled overwhelmingly with Go.The tools that power the internet Docker, Kubernetes, Terraform, Prometheus, etcd, CockroachDB, Caddy, Traefik, they are all written in Go. It's not a coincidence. Go's performance, binaries and concurrency are perfect for infrastructure software.

Another sweet spot is the use of Microservices and APIs. Go's net/http package is production-ready and its frameworks such as Gin, Echo, and Fiber simplify the creation of REST or gRPC applications quickly and efficiently. Handling 100K+ requests per second with regular hardware is nothing new for a Go HTTP server.

Go produces a single binary, it is ideal for distributing command-line tools. Install Go CLI: copy a file. No runtime requirements, no conflicts with other versions. This is why there are tons of DevOps tools that ship Go binaries.

Go vs. the competition

Go vs. Python

Go is 10-100 times faster in CPU-centric tasks and much more efficient in terms of memory and CPU resources. While Python is the go to language for data science and scripting, if it's services that must deal with heavy load, then Go will be a better option. Go's type system will also catch entire classes of bugs that Python will allow to enter production.

Go vs. Rust

Rust provides high degree of control and performance, but requires a very steep learning curve (borrow checker) and slower development velocity. When the performance of 95% of Rust is required with less than 10% of the learning curve, Go is the pragmatic option. Both are good — Go is the "get it shipped" language.

Go vs. Java / Node.js

It requires less memory than Java (no JVM overhead) and loads up in milliseconds, which is important for serverless and containerized deployments. Go's event-driven roots are shared by Node.js, which has difficulty with CPU-intensive tasks. Go is efficient with I/O and computation, without callbacks and async/await complexity.

Why Go is accelerating

The industry now has firmly moved into the containerized, distributed, cloud-native architecture. All the large cloud providers have had a lot of fun with Go. Major companies such as Google, Cloudflare, Uber, Twitch, Dropbox and Stripe have large Go code bases.

There's a flywheel effect with the language:

  1. More infrastructure is written in Go
  2. More engineers need to learn Go
  3. More companies hire Go engineers
  4. Even more infrastructure gets written in Go

Generics were introduced in Go 1.18 (2022) to address the longest-standing complaint in Go, and to start a new wave of library development. The system of modules developed. The toolchain sped up. Go in 2024 is a meaningful improvement not a complete overhaul of Go in 2018, and still retains all the original features.

The simplicity is not a weakness, it is the strength of Go. Better code by any person who can read it than by any genius that can write it, in large groups.

Who should learn Go?

Not all the tasks can be accomplished with Go. However, if your project involves any of these aspects, it is definitely worth considering:

  • Backend / API engineers building services that need to be fast, reliable, and maintainable by a team
  • DevOps / Platform engineers building tooling, CLIs, or anything touching Kubernetes or cloud infrastructure
  • Python developers hitting performance walls — Go is the natural next step when your service can't keep up with traffic
  • Anyone building distributed systems — Go's concurrency primitives and ecosystem are ideal for this domain

Where Go still falls short

Honestly addressing limits is important to a fair assessment.

  • A frequent criticism is the return of err if it is not nil dozens of times in a function. The explicitness is real useful, but there have been proposals for cleaner syntax for years.
  • Generics are not yet fully developed. Not all of them have been accepted into the standard library, and some patterns are not idiomatic in Go.
  • Go is not competitive in areas that demand maximum low-level control (embedded systems, OS kernels), vast mathematical computation (ML training) or rich GUI applications. Python is for data science, Rust is for bare metal and Go is for the middle layer.

Getting started

Go's onboarding is genuinely good. The official tour at go.dev/tour is interactive and covers the essentials in a few hours.

# Install Go (macOS with Homebrew)
brew install go

# Or download from go.dev/dl

# Create a new module
mkdir myapp && cd myapp
go mod init github.com/you/myapp

# Write your first program, then:
go run main.go        # run directly
go build -o ./bin/app # compile to binary
go test ./...         # run all tests

# Your binary: one file, zero dependencies
./bin/app
Enter fullscreen mode Exit fullscreen mode

The Go community is friendly and the simplicity of the language makes other people's Go code really a fun to read. Begin with the tour and then read an article from a source you used for a project – Caddy or Prometheus are good sources.

The bottom line

In 2009, Go wagered that simplicity, speed and pragmatism would be more important than expressiveness. So, that gamble paid off big time 15 years ago. The language of the cloud-native revolution, and Docker and Kubernetes, is not going away… it's moving faster.

If you haven't taken a closer look at Go, you should now! It's easy to learn, it's got a great job market, and it's an ever more integral part of software development, solving problems that are increasingly relevant.

Top comments (0)