Learning Go

Book description

Go is rapidly becoming the preferred language for building web services. While there are plenty of tutorials available that teach Go's syntax to developers with experience in other programming languages, 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. You'll also get a preview of Go's upcoming generics support and how it fits into the language.

  • Learn how to write idiomatic code in Go and design a Go project
  • Understand the reasons for the design decisions in Go
  • 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

Publisher resources

View/Submit Errata

Table of contents

  1. Preface
    1. Who Should Read This Book
    2. Conventions Used in This Book
    3. Using Code Examples
    4. O’Reilly Online Learning
    5. How to Contact Us
    6. Acknowledgments
  2. 1. Setting Up Your Go Environment
    1. Installing the Go Tools
    2. The Go Workspace
    3. The go Command
      1. go run and go build
      2. Getting Third-Party Go Tools
      3. Formatting Your Code
    4. Linting and Vetting
    5. Choose Your Tools
      1. Visual Studio Code
      2. GoLand
      3. The Go Playground
    6. Makefiles
    7. Staying Up to Date
    8. Wrapping Up
  3. 2. Primitive Types and Declarations
    1. Built-in Types
      1. The Zero Value
      2. Literals
      3. Booleans
      4. Numeric Types
      5. A Taste of Strings and Runes
      6. Explicit Type Conversion
    2. var Versus :=
    3. Using const
    4. Typed and Untyped Constants
    5. Unused Variables
    6. Naming Variables and Constants
    7. Wrapping Up
  4. 3. Composite Types
    1. Arrays—Too Rigid to Use Directly
    2. Slices
      1. len
      2. append
      3. Capacity
      4. make
      5. Declaring Your Slice
      6. Slicing Slices
      7. Converting Arrays to Slices
      8. copy
    3. Strings and Runes and Bytes
    4. Maps
      1. Reading and Writing a Map
      2. The comma ok Idiom
      3. Deleting from Maps
      4. Using Maps as Sets
    5. Structs
      1. Anonymous Structs
      2. Comparing and Converting Structs
    6. Wrapping Up
  5. 4. Blocks, Shadows, and Control Structures
    1. Blocks
      1. Shadowing Variables
      2. Detecting Shadowed Variables
    2. if   
    3. for, Four Ways
      1. The Complete for Statement
      2. The Condition-Only for Statement
      3. The Infinite for Statement
      4. break and continue
      5. The for-range Statement
      6. Labeling Your for Statements
      7. Choosing the Right for Statement
    4. switch
    5. Blank Switches
    6. Choosing Between if and switch
    7. goto—Yes, goto
    8. Wrapping Up
  6. 5. Functions
    1. Declaring and Calling Functions
      1. Simulating Named and Optional Parameters
      2. Variadic Input Parameters and Slices
      3. Multiple Return Values
      4. Multiple Return Values Are Multiple Values
      5. Ignoring Returned Values
      6. Named Return Values
      7. Blank Returns—Never Use These!
    2. Functions Are Values
      1. Function Type Declarations
      2. Anonymous Functions
    3. Closures
      1. Passing Functions as Parameters
      2. Returning Functions from Functions
    4. defer
    5. Go Is Call By Value
    6. Wrapping Up
  7. 6. Pointers
    1. A Quick Pointer Primer
    2. Don’t Fear the Pointers
    3. Pointers Indicate Mutable Parameters
    4. Pointers Are a Last Resort
    5. Pointer Passing Performance
    6. The Zero Value Versus No Value
    7. The Difference Between Maps and Slices
    8. Slices as Buffers
    9. Reducing the Garbage Collector’s Workload
    10. Wrapping Up
  8. 7. Types, Methods, and Interfaces
    1. Types in Go
    2. Methods
      1. Pointer Receivers and Value Receivers
      2. Code Your Methods for nil Instances
      3. Methods Are Functions Too
      4. Functions Versus Methods
      5. Type Declarations Aren’t Inheritance
      6. Types Are Executable Documentation
      7. iota Is for Enumerations—Sometimes
    3. Use Embedding for Composition
    4. Embedding Is Not Inheritance
    5. A Quick Lesson on Interfaces
    6. Interfaces Are Type-Safe Duck Typing
    7. Embedding and Interfaces
    8. Accept Interfaces, Return Structs
    9. Interfaces and nil
    10. The Empty Interface Says Nothing
    11. Type Assertions and Type Switches
    12. Use Type Assertions and Type Switches Sparingly
    13. Function Types Are a Bridge to Interfaces
    14. Implicit Interfaces Make Dependency Injection Easier
    15. Wire
    16. Go Isn’t Particularly Object-Oriented (and That’s Great)
    17. Wrapping Up
  9. 8. Errors
    1. How to Handle Errors: The Basics
    2. Use Strings for Simple Errors
    3. Sentinel Errors
    4. Errors Are Values
    5. Wrapping Errors
    6. Is and As
    7. Wrapping Errors with defer
    8. panic and recover
    9. Getting a Stack Trace from an Error
    10. Wrapping Up
  10. 9. Modules, Packages, and Imports
    1. Repositories, Modules, and Packages
    2. go.mod
    3. Building Packages
      1. Imports and Exports
      2. Creating and Accessing a Package
      3. Naming Packages
      4. How to Organize Your Module
      5. Overriding a Package’s Name
      6. Package Comments and godoc
      7. The internal Package
      8. The init Function: Avoid if Possible
      9. Circular Dependencies
      10. Gracefully Renaming and Reorganizing Your API
    4. Working with Modules
      1. Importing Third-Party Code
      2. Working with Versions
      3. Minimal Version Selection
      4. Updating to Compatible Versions
      5. Updating to Incompatible Versions
      6. Vendoring
      7. pkg.go.dev
      8. Additional Information
    5. Publishing Your Module
    6. Versioning Your Module
    7. Module Proxy Servers
      1. Specifying a Proxy Server
      2. Private Repositories
    8. Wrapping Up
  11. 10. Concurrency in Go
    1. When to Use Concurrency
    2. Goroutines
    3. Channels
      1. Reading, Writing, and Buffering
      2. for-range and Channels
      3. Closing a Channel
      4. How Channels Behave
    4. select
    5. Concurrency Practices and Patterns
      1. Keep Your APIs Concurrency-Free
      2. Goroutines, for Loops, and Varying Variables
      3. Always Clean Up Your Goroutines
      4. The Done Channel Pattern
      5. Using a Cancel Function to Terminate a Goroutine
      6. When to Use Buffered and Unbuffered Channels
      7. Backpressure
      8. Turning Off a case in a select
      9. How to Time Out Code
      10. Using WaitGroups
      11. Running Code Exactly Once
      12. Putting Our Concurrent Tools Together
    6. When to Use Mutexes Instead of Channels
    7. Atomics—You Probably Don’t Need These
    8. Where to Learn More About Concurrency
    9. Wrapping Up
  12. 11. The Standard Library
    1. io and Friends
    2. time
      1. Monotonic Time
      2. Timers and Timeouts
    3. encoding/json
      1. Use Struct Tags to Add Metadata
      2. Unmarshaling and Marshaling
      3. JSON, Readers, and Writers
      4. Encoding and Decoding JSON Streams
      5. Custom JSON Parsing
    4. net/http
      1. The Client
      2. The Server
    5. Wrapping Up
  13. 12. The Context
    1. What Is the Context?
    2. Cancellation
    3. Timers
    4. Handling Context Cancellation in Your Own Code
    5. Values
    6. Wrapping Up
  14. 13. Writing Tests
    1. The Basics of Testing
      1. Reporting Test Failures
      2. Setting Up and Tearing Down
      3. Storing Sample Test Data
      4. Caching Test Results
      5. Testing Your Public API
      6. Use go-cmp to Compare Test Results
    2. Table Tests
    3. Checking Your Code Coverage
    4. Benchmarks
    5. Stubs in Go
    6. httptest
    7. Integration Tests and Build Tags
    8. Finding Concurrency Problems with the Race Checker
    9. Wrapping Up
  15. 14. Here There Be Dragons: Reflect, Unsafe, and Cgo
    1. Reflection Lets Us Work with Types at Runtime
      1. Types, Kinds, and Values
      2. Making New Values
      3. Use Reflection to Check If an Interface’s Value Is nil
      4. Use Reflection to Write a Data Marshaler
      5. Build Functions with Reflection to Automate Repetitive Tasks
      6. You Can Build Structs with Reflection, but Don’t
      7. Reflection Can’t Make Methods
      8. Only Use Reflection If It’s Worthwhile
    2. unsafe Is Unsafe
      1. Use unsafe to Convert External Binary Data
      2. unsafe Strings and Slices
      3. unsafe Tools
    3. Cgo Is for Integration, Not Performance
    4. Wrapping Up
  16. 15. Welcome to the Future: Generics in Go
    1. Generics Reduce Repetitive Code and Increase Type Safety
    2. Introducing Generics in Go
    3. Generic Functions Abstract Algorithms
    4. Generics and Interfaces
    5. Use Type Terms to Specify Operators
    6. Type Inference and Generics
    7. Type Elements Limit Constants
    8. Combining Generic Functions with Generic Data Structures
    9. Things That Are Left Out
    10. Idiomatic Go and Generics
    11. Further Futures Unlocked
    12. Wrapping Up
  17. Index
  18. About the Author

Product information

  • Title: Learning Go
  • Author(s): Jon Bodner
  • Release date: March 2021
  • Publisher(s): O'Reilly Media, Inc.
  • ISBN: 9781492077169