Effective Go Recipes
Fast Solutions to Common Tasks
by Miki Tebeka
Programmers love Go because it is lightweight, easy to work with, and
easy to read. Go gives you the benefits of dynamically typed languages
(speed of development) while keeping the upsides of strongly typed
languages (security and performance).
Go is a simple language, but programming in Go is about more than just
mastering syntax. There’s an art to using Go effectively. Squeeze out
the full use of advanced networking and multi-core power for which Go
was designed. Save precious coding hours with recipes that help you
manage objects, collect garbage, and safely use memory. Tackle Unicode,
concurrency, and serialization with ease.
All the clean, reusable solutions you need for a wide variety of
problems common to Go development. Outfitted with these recipes, your
next apps will be more polished and more maintainable than ever.
Start out by tackling time and see how the Go time packager provides
types that will do most of the heavy lifting for you. Next, work on
recipes tailored to the nuances of processing text, like normalizing
strings to avoid bugs. From there, whip up some functions on-the-fly and
store functions in variables and data structures.
Ever wondered why Go seems to be peppered with error handling? Working
through the next recipes, you’ll discover the benefits, which include
more robust code. In the section on HTTP, you’ll learn tricks like
running multiple HTTP servers on the same port and setting timeouts.
With concurrency recipes, you’ll limit the number of goroutines to
improve performance, give your code awareness of timeouts, and decide
when to keep your code sequential instead of making it concurrent.
Throughout the book, you’ll make Go sizzle following simple recipes and
tweaking them to fit your own apps. Using tools like strong typing and
concurrency primitives, build a Go codebase that stays maintainable at
scale.
What You Need
You should know the Go language syntax and have some experience in
programming.
You will need a Go SDK, a Git client, and for some of the chapters, a C
compiler.
Resources
Releases:
- P1.0 2024/04/05
- B7.0 2024/01/15
- B6.0 2023/12/13
- B5.0 2023/11/14
- Preface
- Cooking with Go
- Who Are You?
- Reading This Book
- A Foolish Consistency Is the Hobgoblin of Little Minds
- Wait! There’s More! (online)
- Reading and Writing (I/O)
- Using In-Memory Readers and Writers to Support []byte
- Compressing Old Log Files
- Using bytes.Buffer to Generate SQL
- Conditionally Decompressing Files
- Implementing io.Writer for Frequency Calculation
- Using os.Pipe for Dynamic Data Generation
- Searching in a Memory Mapped File
- Serializing Data
- Streaming Events with encoding/gob
- Parsing Complex JSON Documents
- Streaming JSON
- Handling Missing Values in JSON
- Serializing Custom Types
- Unmarshaling Dynamic Types
- Parsing Struct
Tags
- Utilizing HTTP
- Making GET Requests
- Streaming POST Requests
- Writing Middleware to Monitor Performance
- Setting Server Timeouts
- Supporting Several API Versions in the Same HTTP Server
- Working with Text
- Using Formatting Verbs for Better Output
- Adding String Representation to Your Types
- Detecting Encoding
- Using Regular Expressions to Convert camelCase
to lower_with_underscore
- Folding Strings for Case-Insensitive Comparison
- Using Unicode Normalization for Comparison
- Working with Functions
- Using a Function Registry
- Using Functions as Options
- Using Closures to Provide Options with Arguments
- Passing Notifications with Functions
- Accessing Unexported Functions
- Working with Basic Types
- Using the comma, ok Paradigm
- Using a Slice to Implement a Stack
- Calculating Cumulative Sum
- Serializing Time to/from JSON
- Using Composite Keys in
Maps
- Parsing Time Strings
- Working with Structs, Methods, and Interfaces
- Using Ad Hoc Interfaces
- Wrapping the http.ResponseWriter Interface
- Using Generics to Reduce Code Size
- Using Generics for Type-Safe Data Structures
- Using Generics for Better Type Safety
- Working with Errors
- Handling and Returning Errors
- Handling Panics
- Handling Panics in
Goroutines
- Checking Errors
- Wrapping Errors
- Using Goroutines, Channels, and Context for Concurrency
- Converting Sequential Code to Parallel
- Limiting the Number of Goroutines with a Buffered Channel
- Using a Worker Pool with Channels
- Using context.Context for Timeouts
- Passing Logger with Request ID in Context
- Lower-Level Concurrency
- Writing Idempotent Functions with sync.Once
- Waiting for Job Completion with sync.WaitGroup
- Allowing Multiple Readers with sync.RWMutex
- Using the Race Detector
- Using sync/atomic for a Faster Now
- Working with Sockets
- Accepting Files over TCP Sockets
- Sending Files over TCP Sockets
- Writing a Serverless Platform
- Reading Time with NTP over UDP
- Communicating with Non-Go Code
- Using os/exec to Ping Servers
- Calling C Functions to AlignText
- Redirecting Subprocess stdin and stdout to Prototype a Calculator
- Stemming Words Using a C Library
- Testing Your Code
- Conditionally Running Continuous Integration Tests
- Reading Test Cases from a File
- Fuzzing Bugs Away
- Mocking HTTP Client Calls
- Writing Global Setup/Teardown Functions
- Running Services in Testing
- Writing a Linter
- Building Applications
- Embedding Assets in Your Binary
- Injecting Version to Your Executable
- Ensuring Static Builds
- Using Build Tags for Conditional Builds
- Building Executables for Different Platforms
- Generating Code
- Shipping Your Code
- Configuring Your Application
- Patching Dependencies
- Packaging Applications in Docker
- Catching Signals for Graceful Shutdown
- Writing Logs
- Using Metrics as Eyes to Production
- Debugging Running Services
Author
Miki has a B.Sc. in computer science from Ben Gurion University. He
is the CEO of 353solutions, where he teaches and writes code in Go,
Python, and Scientific Python. Miki has authored several books and is a
LinkedIn learning author. He also organizes and give talks at several
conferences around the world.