Go has rapidly become the preferred language for building web services. Plenty of tutorials are available to teach Go's syntax to developers with experience in other programming languages, but tutorials aren't enough. They don't teach Go's idioms, so developers end up recreating patterns that don't make sense in a Go context. This practical guide provides the essential background you need to write clear and idiomatic Go.
No matter your level of experience, you'll learn how to think like a Go developer. Author Jon Bodner introduces the design patterns experienced Go developers have adopted and explores the rationale for using them. This updated edition also shows you how Go's generics support fits into the language.
This book helps you:
• Write idiomatic code in Go and design a Go project
• Understand the reasons behind Go's design decisions
• Set up a Go development environment for a solo developer or team
• Learn how and when to use reflection, unsafe, and cgo
• Discover how Go's features allow the language to run efficiently
• Know which Go features you should use sparingly or not at all
• Use Go's tools to improve performance, optimize memory usage, and reduce garbage collection
• Learn how to use Go's advanced development tools
Author(s): Jon Bodner
Edition: 2
Publisher: O'Reilly Media
Year: 2024
Language: English
Commentary: Publisher's PDF
Pages: 491
City: Sebastopol, CA
Tags: Programming; Concurrency; Modules; Packages; Go; Error Handling; Closures; Testing; Standard Library; Elementary
Copyright
Table of Contents
Preface
Who Should Read This Book
Conventions Used in This Book
Using Code Examples
O’Reilly Online Learning
How to Contact Us
Acknowledgments for the 2nd Edition
Acknowledgments for the 1st Edition
Chapter 1. Setting Up Your Go Environment
Installing the Go Tools
Troubleshooting Your Go Installation
Go Tooling
Your First Go Program
Making a Go Module
go build
go fmt
go vet
Choose Your Tools
Visual Studio Code
GoLand
The Go Playground
Makefiles
The Go Compatibility Promise
Staying Up-to-Date
Exercises
Wrapping Up
Chapter 2. Predeclared Types and Declarations
The Predeclared Types
The Zero Value
Literals
Booleans
Numeric Types
A Taste of Strings and Runes
Explicit Type Conversion
Literals Are Untyped
var Versus :=
Using const
Typed and Untyped Constants
Unused Variables
Naming Variables and Constants
Exercises
Wrapping Up
Chapter 3. Composite Types
Arrays—Too Rigid to Use Directly
Slices
len
append
Capacity
make
Emptying a Slice
Declaring Your Slice
Slicing Slices
copy
Converting Arrays to Slices
Converting Slices to Arrays
Strings and Runes and Bytes
Maps
Reading and Writing a Map
The comma ok Idiom
Deleting from Maps
Emptying a Map
Comparing Maps
Using Maps as Sets
Structs
Anonymous Structs
Comparing and Converting Structs
Exercises
Wrapping Up
Chapter 4. Blocks, Shadows, and Control Structures
Blocks
Shadowing Variables
if
for, Four Ways
The Complete for Statement
The Condition-Only for Statement
The Infinite for Statement
break and continue
The for-range Statement
Labeling Your for Statements
Choosing the Right for Statement
switch
Blank Switches
Choosing Between if and switch
goto—Yes, goto
Exercises
Wrapping Up
Chapter 5. Functions
Declaring and Calling Functions
Simulating Named and Optional Parameters
Variadic Input Parameters and Slices
Multiple Return Values
Multiple Return Values Are Multiple Values
Ignoring Returned Values
Named Return Values
Blank Returns—Never Use These!
Functions Are Values
Function Type Declarations
Anonymous Functions
Closures
Passing Functions as Parameters
Returning Functions from Functions
defer
Go Is Call by Value
Exercises
Wrapping Up
Chapter 6. Pointers
A Quick Pointer Primer
Don’t Fear the Pointers
Pointers Indicate Mutable Parameters
Pointers Are a Last Resort
Pointer Passing Performance
The Zero Value Versus No Value
The Difference Between Maps and Slices
Slices as Buffers
Reducing the Garbage Collector’s Workload
Tuning the Garbage Collector
Exercises
Wrapping Up
Chapter 7. Types, Methods, and Interfaces
Types in Go
Methods
Pointer Receivers and Value Receivers
Code Your Methods for nil Instances
Methods Are Functions Too
Functions Versus Methods
Type Declarations Aren’t Inheritance
Types Are Executable Documentation
iota Is for Enumerations—Sometimes
Use Embedding for Composition
Embedding Is Not Inheritance
A Quick Lesson on Interfaces
Interfaces Are Type-Safe Duck Typing
Embedding and Interfaces
Accept Interfaces, Return Structs
Interfaces and nil
Interfaces Are Comparable
The Empty Interface Says Nothing
Type Assertions and Type Switches
Use Type Assertions and Type Switches Sparingly
Function Types Are a Bridge to Interfaces
Implicit Interfaces Make Dependency Injection Easier
Wire
Go Isn’t Particularly Object-Oriented (and That’s Great)
Exercises
Wrapping Up
Chapter 8. Generics
Generics Reduce Repetitive Code and Increase Type Safety
Introducing Generics in Go
Generic Functions Abstract Algorithms
Generics and Interfaces
Use Type Terms to Specify Operators
Type Inference and Generics
Type Elements Limit Constants
Combining Generic Functions with Generic Data Structures
More on comparable
Things That Are Left Out
Idiomatic Go and Generics
Adding Generics to the Standard Library
Future Features Unlocked
Exercises
Wrapping Up
Chapter 9. Errors
How to Handle Errors: The Basics
Use Strings for Simple Errors
Sentinel Errors
Errors Are Values
Wrapping Errors
Wrapping Multiple Errors
Is and As
Wrapping Errors with defer
panic and recover
Getting a Stack Trace from an Error
Exercises
Wrapping Up
Chapter 10. Modules, Packages, and Imports
Repositories, Modules, and Packages
Using go.mod
Use the go Directive to Manage Go Build Versions
The require Directive
Building Packages
Importing and Exporting
Creating and Accessing a Package
Naming Packages
Overriding a Package’s Name
Documenting Your Code with Go Doc Comments
Using the internal Package
Avoiding Circular Dependencies
Organizing Your Module
Gracefully Renaming and Reorganizing Your API
Avoiding the init Function if Possible
Working with Modules
Importing Third-Party Code
Working with Versions
Minimal Version Selection
Updating to Compatible Versions
Updating to Incompatible Versions
Vendoring
Using pkg.go.dev
Publishing Your Module
Versioning Your Module
Overriding Dependencies
Retracting a Version of Your Module
Using Workspaces to Modify Modules Simultaneously
Module Proxy Servers
Specifying a Proxy Server
Using Private Repositories
Additional Details
Exercises
Wrapping Up
Chapter 11. Go Tooling
Using go run to Try Out Small Programs
Adding Third-Party Tools with go install
Improving Import Formatting with goimports
Using Code-Quality Scanners
staticcheck
revive
golangci-lint
Using govulncheck to Scan for Vulnerable Dependencies
Embedding Content into Your Program
Embedding Hidden Files
Using go generate
Working with go generate and Makefiles
Reading the Build Info Inside a Go Binary
Building Go Binaries for Other Platforms
Using Build Tags
Testing Versions of Go
Using go help to Learn More About Go Tooling
Exercises
Wrapping Up
Chapter 12. Concurrency in Go
When to Use Concurrency
Goroutines
Channels
Reading, Writing, and Buffering
Using for-range and Channels
Closing a Channel
Understanding How Channels Behave
select
Concurrency Practices and Patterns
Keep Your APIs Concurrency-Free
Goroutines, for Loops, and Varying Variables
Always Clean Up Your Goroutines
Use the Context to Terminate Goroutines
Know When to Use Buffered and Unbuffered Channels
Implement Backpressure
Turn Off a case in a select
Time Out Code
Use WaitGroups
Run Code Exactly Once
Put Your Concurrent Tools Together
When to Use Mutexes Instead of Channels
Atomics—You Probably Don’t Need These
Where to Learn More About Concurrency
Exercises
Wrapping Up
Chapter 13. The Standard Library
io and Friends
time
Monotonic Time
Timers and Timeouts
encoding/json
Using Struct Tags to Add Metadata
Unmarshaling and Marshaling
JSON, Readers, and Writers
Encoding and Decoding JSON Streams
Custom JSON Parsing
net/http
The Client
The Server
ResponseController
Structured Logging
Exercises
Wrapping Up
Chapter 14. The Context
What Is the Context?
Values
Cancellation
Contexts with Deadlines
Context Cancellation in Your Own Code
Exercises
Wrapping Up
Chapter 15. Writing Tests
Understanding the Basics of Testing
Reporting Test Failures
Setting Up and Tearing Down
Testing with Environment Variables
Storing Sample Test Data
Caching Test Results
Testing Your Public API
Using go-cmp to Compare Test Results
Running Table Tests
Running Tests Concurrently
Checking Your Code Coverage
Fuzzing
Using Benchmarks
Using Stubs in Go
Using httptest
Using Integration Tests and Build Tags
Finding Concurrency Problems with the Data Race Detector
Exercises
Wrapping Up
Chapter 16. Here Be Dragons: Reflect, Unsafe, and Cgo
Reflection Lets You Work with Types at Runtime
Types, Kinds, and Values
Make New Values
Use Reflection to Check If an Interface’s Value Is nil
Use Reflection to Write a Data Marshaler
Build Functions with Reflection to Automate Repetitive Tasks
You Can Build Structs with Reflection, but Don’t
Reflection Can’t Make Methods
Use Reflection Only if It’s Worthwhile
unsafe Is Unsafe
Using Sizeof and Offsetof
Using unsafe to Convert External Binary Data
Accessing Unexported Fields
Using unsafe Tools
Cgo Is for Integration, Not Performance
Exercises
Wrapping Up
Index
About the Author
Colophon