Go
Introduction to Go
Go was created at Google in 2009, explicitly to fix pain points its creators had with C++ at scale: slow builds, hard-to-manage dependencies, and concurrency that was easy to get wrong. The result is a language that looks almost nothing like C++'s answer to those problems — smaller, more opinionated, and built around one specific idea: make it easy to write software that does many things at once, correctly.
- What it is
- A compiled, statically-typed, garbage-collected language with built-in concurrency support, a fast compiler, and a deliberately small feature set.
- Mental model
- If C++ says "give the programmer every tool and trust them," Go says "give the programmer fewer tools, chosen carefully, so any Go codebase looks roughly like any other."
- Key numbers
- Files use the
.goextension;go buildtypically compiles in seconds even for large codebases — a deliberate design goal, not an accident. - Reach for it when
- Building networked services, CLI tools, or anything needing straightforward concurrency — less commonly the first choice for hard real-time or deeply resource-constrained embedded targets (see this domain's closing chapter for exactly why and where it still fits).
Go's design philosophy, by contrast
| C / C++ | Go | |
|---|---|---|
| Memory management | Manual (C) or RAII/smart pointers (C++) | Automatic garbage collection — no free, no delete |
| Error handling | Return codes (C) or exceptions (C++) | Explicit multi-value returns, checked by convention — no exceptions at all |
| Object-oriented features | None (C) or classes/inheritance (C++) | Structs with methods, but no inheritance — composition and interfaces instead |
| Concurrency | OS threads, manual synchronization | Goroutines and channels, built directly into the language |
| Compile speed | Can be slow on large C++ codebases | A deliberate, explicit design goal — typically very fast |
None of this makes Go strictly "better" — it's a different set of tradeoffs, optimized for different priorities than C or C++'s. Every chapter in this domain calls out exactly which tradeoff is being made and why.
A first program, line by line
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
package main- Every Go file belongs to a package —
mainspecifically marks this as a standalone, runnable program rather than a reusable library. import "fmt"- Brings in the "format" package, Go's standard library equivalent of C's
<stdio.h>—fmt.Printlnis the direct analog ofprintf. func main()- Exactly like C's
main— the entry point every Go program starts running from. No return type, no arguments needed for the simple case. - No semicolons
- Go statements don't end in
;in normal source — the compiler inserts them automatically based on line breaks. This is a real, visible difference from every C-family syntax you've seen so far.
The toolchain
go run hello.go # compile AND run in one step — great for quick iteration
go build hello.go # compile to a binary named "hello", don't run it
./hello # run the compiled binary
go fmt hello.go # reformat the file to Go's standard style, automatically
go fmt is worth calling out specifically — Go ships an opinionated auto-formatter as a core
tool, and the entire Go ecosystem uses it by convention. There's no equivalent debate over code style
that C/C++ projects often have, because the tooling settles it.
A map of what's ahead
- Variables, Types & Control Flow — declarations, the built-in types,
if/for/switch. - Functions & Multiple Return Values — Go functions can return more than one value directly — the mechanism behind Go's entire error-handling convention.
- Structs & Methods — Go's answer to C++ classes, without inheritance.
- Interfaces — Go's answer to C++ polymorphism, structured completely differently.
- Slices, Arrays & Maps — Go's built-in collection types.
- Goroutines & Channels — Go's concurrency model, the feature most associated with the language.
- Error Handling — the explicit-multi-return convention in full, and why Go has no exceptions.
- Packages & Modules — organizing and sharing Go code.
- Go for Embedded/IoT — where Go genuinely fits on constrained hardware, and TinyGo.
Real-world applications
- Docker and Kubernetes — both written in Go, arguably the projects most responsible for the language's rise in infrastructure/DevOps tooling.
- Networked backend services — Go's built-in concurrency makes it a strong natural fit for servers handling many simultaneous connections.
- CLI tools — Go compiles to a single, dependency-free binary per platform, a genuinely convenient distribution story for command-line tools.
Gotchas
- An unused import or an unused local variable is a compile error in Go, not just a warning — stricter than C/C++ by design, and a common early surprise.
- Go's braces are mandatory and must follow a specific placement (the opening brace can't go on its own line) — this isn't a style preference, it's enforced by the automatic semicolon insertion mentioned above.
- Go deliberately has no
whilekeyword —foralone covers every loop shape, one more example of Go choosing fewer ways to do the same thing.