1 Getting started
This opening chapter sets the tone and goals of the book: learn Go by building realistic projects while developing an instinct for idiomatic, readable, and testable code. It argues that although Go is easy to pick up, mastering it requires understanding the language’s conventions and mechanics. Aimed at experienced developers, it champions a hands-on, example-driven path—building command-line tools, concurrent programs, and HTTP services—so readers can see when and why to use specific features, avoid common pitfalls, and cultivate a pragmatic mindset focused on maintainability.
At a high level, the chapter surveys Go’s core strengths. Go is statically and strongly typed yet ergonomic, compiles fast to efficient native binaries, and ships a runtime that provides a lightweight scheduler and concurrent garbage collector. Concurrency is first-class via goroutines and channels inspired by CSP, enabling scalable, understandable pipelines—used judiciously rather than by default. Go’s type system favors composition over inheritance and achieves flexible, reliable polymorphism through implicit interfaces, which in turn promotes modular design and inherently testable code (for example, swapping real dependencies with fakes in tests by depending on small interfaces).
The chapter also highlights Go’s rich standard library and cohesive tooling. Developers can quickly assemble robust servers and clients with batteries-included packages, while the go tool offers unified commands for building, testing, formatting, vetting, documenting, and managing modules—driving consistency and speed. It explains why Go was created to remove unnecessary complexity and where it excels (CLIs, services, distributed systems), notes its widespread adoption, and closes with practical next steps: install Go, initialize a module, and proceed through the book and appendices to deepen fluency in idioms, testing, and real-world program structure.
The Go compiler compiles code with all necessary dependencies into a single executable binary targeted for a specific operating system and architecture.
A statically linked binary that includes everything it needs to run.
The go statement before a function spawns a new goroutine that runs the given function concurrently. This visual illustrates running the crawl function concurrently in two separate goroutines.
The scheduler multiplexes goroutines onto threads for efficiency. Parallelism occurs at runtime when multiple CPU cores can run multiple threads in parallel.
Goroutines that are running concurrently communicate over channels. These goroutines forward the message to the next goroutine, each performing some computation on the received message before sending it to the next one.
While inheritance creates a type hierarchy, embedding does not. In inheritance, you can pass parent (square) and child (circle) types interchangeably to a function that expects only the parent type. With embedding, the function can only work with the specified type. Embedding does not form a type hierarchy. Embedding simply makes one type's methods and data part of another type.
The function expects a type that implements the runner interface (any type with a run() method). You can interchangeably pass either of these types to the function because each has a run() method and implicitly satisfies runner.
This expensive test runs code that invokes the Charge method of Mithril's API and contacts live servers. It's not the best way of testing.
Testing the code with a fake payment provider. The code no longer uses Mithril's API methods. Instead, it uses a fake payment provider.
Summary
- This book will be your guide to writing idiomatic and testable code.
- Learning through examples is an effective way to learn a new technology.
- Go is a simple and effective programming language.
- Go fuses the best sides of dynamically and statically typed languages.
- Go code is written in packages and compiled into efficient native machine code.
- The compiler produces a single static binary, making deployment straightforward.
- Go executables include the Go Runtime, which has a scheduler for concurrent execution and a garbage collector that reclaims unreferenced memory.
- Concurrency is built into Go. There is no difference between writing sequential and concurrent code. It is straightforward to turn the former into the latter.
- The Go scheduler abstracts the operating system scheduler and threads.
- Goroutines are independently running concurrent functions.
- Channels allow goroutines to communicate and synchronize with each other.
- Go's type system is flat and favors composition over inheritance.
- Interfaces provide polymorphism and are implicitly satisfied.
- The standard library includes a comprehensive set of packages that support a broad range of programming tasks, facilitating rapid development.
- Go's extensive tooling streamlines development workflows.
Go by Example ebook for free