DEV Community

The Practical Developer
The Practical Developer

Posted on Originally published at practicaldevblog.blogspot.com

Go Explained: Simple Code That Runs Fast

Introduction

Go was built at Google for a specific frustration: large programs that were slow to build and hard to read. The answer was a language that is deliberately small — fewer features, but the right ones, done well.

If you know one programming language already, Go will feel familiar within an hour. The interesting parts are not the syntax, but two ideas: goroutines and channels.

Goroutines: cheap concurrency

Most languages make running things at the same time feel heavy — threads, thread pools, and careful setup. A goroutine is Go's lightweight version: you start one by writing go in front of a function call.

package main

import (
    "fmt"
    "time"
)

func say(text string) {
    for i := 0; i < 3; i++ {
        fmt.Println(text)
        time.Sleep(100 * time.Millisecond)
    }
}

func main() {
    go say("hello")
    say("world")
    time.Sleep(500 * time.Millisecond)
}
Enter fullscreen mode Exit fullscreen mode

The go say("hello") line does not wait — it starts a goroutine and moves on, so "hello" and "world" print interleaved. Goroutines are cheap enough that a program can run thousands of them, where thousands of operating-system threads would struggle.

Channels: how goroutines talk

Goroutines that never communicate are not very useful. A channel is a pipe between them: one goroutine sends a value in, another receives it.

package main

import "fmt"

func worker(done chan bool) {
    fmt.Println("Working...")
    done <- true
}

func main() {
    done := make(chan bool)
    go worker(done)
    <-done // Wait until the worker sends its signal
    fmt.Println("Done!")
}
Enter fullscreen mode Exit fullscreen mode

The <-done line blocks until the worker sends true, which is how the main program waits without guessing how long the work will take. The famous Go saying sums it up: "Do not communicate by sharing memory; instead, share memory by communicating."

Why Go skips the features

Go deliberately leaves things out: no classes, no inheritance, no generics in the original design, no exceptions. Instead you get:

  • Structs and interfaces for organising data and behaviour, without class hierarchies.
  • Explicit error returns — a function returns its result and an error, and you check it, instead of exceptions jumping across the program.
  • A single formatting tool (gofmt) so all Go code looks the same, ending style arguments forever.

This can feel restrictive at first. The payoff is code that a new team member can read and understand quickly, even in a large codebase.

Where Go shines

Go is most at home in backend services, command-line tools, and cloud infrastructure — Docker and Kubernetes are both written in Go. If you need a fast API server, a small tool that compiles to a single binary, or a service handling many connections at once, Go is a strong default choice.

Takeaway

Go trades features for clarity: goroutines for cheap concurrency, channels for communication between them, and explicit errors instead of exceptions. Write a small program, add one goroutine, and you have felt the core of the language.

Originally published at https://practicaldevblog.blogspot.com/2026/10/go-explained-simple-code-that-runs-fast.html

Top comments (0)