📄 Page
1
(This page has no text content)
📄 Page
2
Praise for Learning Go “Go is unique and even experienced programmers have to unlearn a few things and think differently about software. Learning Go does a good job of working through the big features of the language while pointing out idiomatic code, pitfalls, and design patterns along the way.” —Aaron Schlesinger, Sr. Engineer, Microsoft “Jon has been a critical voice in the Go community for many years and we have been strongly benefitted from his talks and articles. With Learning Go, Jon has written the programmers’ guide to learning Go. It strikes just the right balance of giving a good overview of what you need to know without rehashing well understood concepts from other languages.” —Steve Francia, Go language product lead, Google, and author of Hugo, Cobra, and Viper “Bodner gets Go. In clear, lively prose, he teaches the language from its basics to advanced topics like reflection and C interop. He demonstrates through numerous examples how to write idiomatic Go, with its emphasis on clarity and simplicity. He also takes the time to explain the underlying concepts that can affect your program’s behavior, like the effects of pointers on memory layout and garbage collection. Beginners who read this book will come up to speed quickly, and even experienced Go programmers are likely to learn something." —Jonathan Amsterdam, Software Engineer on the Go team at Google
📄 Page
3
"Learning Go is the essential introduction to what makes the Go programming language unique as well as the design patterns and idioms that make it so powerful. Jon Bodner manages to connect the fundamentals of the language to Go’s philosophy, guiding readers to write Go the way it was meant to be written.” —Robert Liebowitz, Software Engineer at Morning Consult “Jon wrote a book that does more than just reference Go; it provides an idiomatic and practical understanding of the language. Jon’s industry experience is what drives this book, and it will help those looking to be immediately productive in the language.” —William Kennedy, Managing Partner at Ardan Labs
📄 Page
4
Learning Go FIRST EDITION An Idiomatic Approach to Real-World Go Programming Jon Bodner
📄 Page
5
Learning Go by Jon Bodner Copyright © 2021 Jon Bodner. All rights reserved. Printed in the United States of America. Published by O’Reilly Media, Inc., 1005 Gravenstein Highway North, Sebastopol, CA 95472. O’Reilly books may be purchased for educational, business, or sales promotional use. Online editions are also available for most titles (http://oreilly.com). For more information, contact our corporate/institutional sales department: 800-998-9938 or corporate@oreilly.com. Acquisitions Editor: Suzanne McQuade Developmental Editor: Michele Cronin Production Editor: Beth Kelly Copyeditor: Piper Editorial Consulting, LLC Proofreader: Piper Editorial Consulting, LLC Indexer: Judith McConville Interior Designer: David Futato Cover Designer: Karen Montgomery Illustrator: Kate Dullea March 2021: First Edition Revision History for the First Edition
📄 Page
6
2021-03-02: First Release See http://oreilly.com/catalog/errata.csp?isbn=9781492077213 for release details. The O’Reilly logo is a registered trademark of O’Reilly Media, Inc. Learning Go, the cover image, and related trade dress are trademarks of O’Reilly Media, Inc. The views expressed in this work are those of the author, and do not represent the publisher’s views. While the publisher and the author have used good faith efforts to ensure that the information and instructions contained in this work are accurate, the publisher and the author disclaim all responsibility for errors or omissions, including without limitation responsibility for damages resulting from the use of or reliance on this work. Use of the information and instructions contained in this work is at your own risk. If any code samples or other technology this work contains or describes is subject to open source licenses or the intellectual property rights of others, it is your responsibility to ensure that your use thereof complies with such licenses and/or rights. 978-1-492-07721-3 [LSI]
📄 Page
7
Preface My first choice for a book title was Boring Go because, properly written, Go is boring. It might seem a bit weird to write a book on a boring topic, so I should explain. Go has a small feature set that is out of step with most other modern programming languages. Well-written Go programs tend to be straightforward and sometimes a bit repetitive. There’s no inheritance, no generics (yet), no aspect-oriented programming, no function overloading, and certainly no operator overloading. There’s no pattern matching, no named parameters, no exceptions. To the horror of many, there are pointers. Go’s concurrency model is unlike other languages, but it’s based on ideas from the 1970s, as is the algorithm used for its garbage collector. In short, Go feels like a throwback. And that’s the point. Boring does not mean trivial. Using Go correctly requires an understanding of how its features are intended to fit together. While you can write Go code that looks like Java or Python, you’re going to be unhappy with the result and wonder what all the fuss is about. That’s where this book comes in. It walks through the features of Go, explaining how to best use them to write idiomatic code that can grow. When it comes to building things that last, being boring is great. No one wants to be the first person to drive their car over a bridge built with untested techniques that the engineer thought were cool. The modern world depends on software as much as it depends on bridges, perhaps more so. Yet many programming languages add features without thinking about their impact on the maintainability of the codebase. Go is intended for building programs that last, programs that are modified by dozens of developers over dozens of years.
📄 Page
8
Go is boring and that’s fantastic. I hope this book teaches you how to build exciting projects with boring code. Who Should Read This Book This book is targeted at developers who are looking to pick up a second (or fifth) language. The focus is on people who are new to Go. This ranges from those who don’t know anything about Go other than it has a cute mascot, to those who have already worked through a Go tutorial or even written some Go code. The focus for Learning Go isn’t just how to write programs in Go; it’s how to write Go idiomatically. More experienced Go developers can find advice on how to best use the newer features of the language. The most important thing is that the reader wants to learn how to write Go code that looks like Go. Experience is assumed with the tools of the developer trade, such as version control (preferably Git) and IDEs. Readers should be familiar with basic computer science concepts like concurrency and abstraction, as the book explains how they work in Go. Some of the code examples are downloadable from GitHub and dozens more can be tried out online on The Go Playground. While an internet connection isn’t required, it is helpful when reviewing executable examples. Since Go is often used to build and call HTTP servers, some examples assume familiarity with basic HTTP concepts. While most of Go’s features are found in other languages, Go makes different tradeoffs, so programs written in it have a different structure. Learning Go starts by looking at how to set up a Go development environment, and then covers variables, types, control structures, and functions. If you are tempted to skip over this material, resist the urge and take a look. It is often the details that make your Go code idiomatic. Some of what seems obvious at first glance might actually be subtly surprising when you think about it in depth.
📄 Page
9
Conventions Used in This Book The following typographical conventions are used in this book: Italic Indicates new terms, URLs, email addresses, filenames, and file extensions. Constant width Used for program listings, as well as within paragraphs to refer to program elements such as variable or function names, databases, data types, environment variables, statements, and keywords. Constant width bold Shows commands or other text that should be typed literally by the user. Constant width italic Shows text that should be replaced with user-supplied values or by values determined by context. TIP This element signifies a tip or suggestion. NOTE This element signifies a general note.
📄 Page
10
WARNING This element indicates a warning or caution. Using Code Examples Supplemental material (code examples, exercises, etc.) is available for download at https://github.com/learning-go-book. If you have a technical question or a problem using the code examples, please send email to bookquestions@oreilly.com. This book is here to help you get your job done. In general, if example code is offered with this book, you may use it in your programs and documentation. You do not need to contact us for permission unless you’re reproducing a significant portion of the code. For example, writing a program that uses several chunks of code from this book does not require permission. Selling or distributing examples from O’Reilly books does require permission. Answering a question by citing this book and quoting example code does not require permission. Incorporating a significant amount of example code from this book into your product’s documentation does require permission. We appreciate, but do not require, attribution. An attribution usually includes the title, author, publisher, and ISBN. For example: “Learning Go by Jon Bodner (O’Reilly). Copyright 2021 Jon Bodner, 978-1-492-07721-3.” If you feel your use of code examples falls outside fair use or the permission given above, feel free to contact us at permissions@oreilly.com. O’Reilly Online Learning
📄 Page
11
NOTE For more than 40 years, O’Reilly Media has provided technology and business training, knowledge, and insight to help companies succeed. Our unique network of experts and innovators share their knowledge and expertise through books, articles, and our online learning platform. O’Reilly’s online learning platform gives you on-demand access to live training courses, in-depth learning paths, interactive coding environments, and a vast collection of text and video from O’Reilly and 200+ other publishers. For more information, visit http://oreilly.com. How to Contact Us Please address comments and questions concerning this book to the publisher: O’Reilly Media, Inc. 1005 Gravenstein Highway North Sebastopol, CA 95472 800-998-9938 (in the United States or Canada) 707-829-0515 (international or local) 707-829-0104 (fax) We have a web page for this book, where we list errata, examples, and any additional information. You can access this page at https://oreil.ly/learn-go.
📄 Page
12
Email bookquestions@oreilly.com to comment or ask technical questions about this book. For news and information about our books and courses, visit http://oreilly.com. Find us on Facebook: http://facebook.com/oreilly Follow us on Twitter: http://twitter.com/oreillymedia Watch us on YouTube: http://youtube.com/oreillymedia Acknowledgments Writing a book seems like a solitary task, but it doesn’t happen without the help of a great number of people. I mentioned to Carmen Andoh that I wanted to write a book on Go and at GopherCon 2019, and she introduced me to Zan McQuade at O’Reilly. Zan guided me through the acquisition process and continued to provide me advice while I was writing Learning Go. Michele Cronin edited the text, gave feedback, and listened during the inevitable rough patches. Tonya Trybula’s copy editing and Beth Kelly’s production editing made my draft production-quality. While writing, I received critical feedback (and encouragement) from many people including Jonathan Altman, Jonathan Amsterdam, Johnny Ray Austin, Chris Fauerbach, Chris Hines, Bill Kennedy, Tony Nelson, Phil Pearl, Liz Rice, Aaron Schlesinger, Chris Stout, Kapil Thangavelu, Claire Trivisonno, Volker Uhrig, Jeff Wendling, and Kris Zaragoza. I’d especially like to recognize Rob Liebowitz, whose detailed notes and rapid responses made this book far better than it would have been without his efforts. My family put up with me spending nights and weekends at the computer instead of with them. In particular, my wife Laura graciously pretended that I didn’t wake her up when I’d come to bed at 1 A.M. or later.
📄 Page
13
Finally, I want to remember the two people who started me on this path four decades ago. The first is Paul Goldstein, the father of a childhood friend. In 1982, Paul showed us a Commodore PET, typed PRINT 2 + 2, and hit the enter key. I was amazed when the screen said 4 and was instantly hooked. He later taught me how to program and even let me borrow the PET for a few weeks. Second, I’d like to thank my mother for encouraging my interest in programming and computers, despite having no idea what any of it was for. She bought me the BASIC programming cartridge for the Atari 2600, a VIC-20 and then a Commodore 64, along with the programming books that inspired me to want to write my own someday. Thank you all for helping make this dream of mine come true.
📄 Page
14
Chapter 1. Setting Up Your Go Environment Every programming language needs a development environment, and Go is no exception. If you’ve already written a Go program or two, you should have a working environment, but you might have missed out on some of the newer techniques and tools. If this is your first time setting up Go on your computer, don’t worry; installing Go and its supporting tools is easy. After we set up our environment and verify it, we’ll build a simple program, learn about the different ways to build and run Go code, and then explore some tools and techniques that make Go development easier. Installing the Go Tools To write Go code, you first need to download and install the Go development tools. The latest version of the tools can be found at the downloads page on the Go website. Choose the download for your platform and install it. The .pkg installer for Mac and the .msi installer for Windows automatically install Go in the correct location, remove any old installations, and put the Go binary in the default executable path. TIP If you are a Mac developer, you can install Go using Homebrew with the command brew install go. Windows developers who use Chocolatey can install Go with the command choco install golang.
📄 Page
15
The various Linux and FreeBSD installers are gzipped tar files and expand to a directory named go. Copy this directory to /usr/local and add /usr/local/go/bin to your $PATH so that the go command is accessible: $ tar -C /usr/local -xzf go1.15.2.linux-amd64.tar.gz $ echo 'export PATH=$PATH:/usr/local/go/bin' >> $HOME/.profile $ source $HOME/.profile NOTE Go programs compile to a single binary and do not require any additional software to be installed in order to run them. Install the Go development tools only on computers that build Go programs. You can validate that your environment is set up correctly by opening up a terminal or command prompt and typing: $ go version If everything is set up correctly, you should see something like this printed: go version go1.15.2 darwin/amd64 This tells you that this is Go version 1.15.2 on Mac OS. (Darwin is the name of the kernel for Mac OS and amd64 is the name for the 64-bit CPU architecture from both AMD and Intel.) If you get an error instead of the version message, it’s likely that you don’t have go in your executable path, or you have another program named go in your path. On Mac OS and other Unix-like systems, use which go to see the go command being executed, if any. If it isn’t the go command at /usr/local/go/bin/go, you need to fix your executable path.
📄 Page
16
If you’re on Linux or FreeBSD, it’s possible you installed the 64-bit Go development tools on a 32-bit system or the development tools for the wrong chip architecture. The Go Workspace Since the introduction of Go in 2009, there have been several changes in how Go developers organize their code and their dependencies. Because of this churn, there’s lots of conflicting advice, and most of it is obsolete. For modern Go development, the rule is simple: you are free to organize your projects as you see fit. However, Go still expects there to be a single workspace for third- party Go tools installed via go install (see “Getting Third-Party Go Tools”). By default, this workspace is located in $HOME/go, with source code for these tools stored in $HOME/go/src and the compiled binaries in $HOME/go/bin. You can use this default or specify a different workspace by setting the $GOPATH environment variable. Whether or not you use the default location, it’s a good idea to explicitly define GOPATH and to put the $GOPATH/bin directory in your executable path. Explicitly defining GOPATH makes it clear where your Go workspace is located and adding $GOPATH/bin to your executable path makes it easier to run third-party tools installed via go install, which we’ll talk about in a bit. If you are on a Unix-like system using bash, add the following lines to your .profile. (If you are using zsh, add these lines to .zshrc instead): export GOPATH=$HOME/go export PATH=$PATH:$GOPATH/bin You’ll need to source $HOME/.profile to make these changes take effect in your current terminal window.
📄 Page
17
On Windows, run the following commands at the command prompt: setx GOPATH %USERPROFILE%\go setx path "%path%;%USERPROFILE%\bin" After running these commands, you must close your current command prompt and open a new one for these changes to take effect. There are other environment variables that are recognized by the go tool. You can get a complete list, along with a brief description of each variable, using the go env command. Many of them control low- level behavior that can be safely ignored, but we cover some of these variables when discussing modules and cross-compilation. NOTE Some online resources tell you to set the GOROOT environment variable. This variable specifies the location where your Go development environment is installed. This is no longer necessary; the go tool figures this out automatically. The go Command Out of the box, Go ships with many development tools. You access these tools via the go command. They include a compiler, code formatter, linter, dependency manager, test runner, and more. As we learn how to build high-quality idiomatic Go, we’ll explore many of these tools throughout the book. Let’s start with the ones that we use to build Go code and use the go command to build a simple application. go run and go build
📄 Page
18
There are two similar commands available via go: go run and go build. Each takes either a single Go file, a list of Go files, or the name of a package. We are going to create a simple program and see what happens when we use these commands. go run We’ll start with go run. Create a directory called ch1, open up a text editor, enter the following text, and save it inside ch1 to a file named hello.go: package main import "fmt" func main() { fmt.Println("Hello, world!") } After the file is saved, open up a terminal or command prompt and type: go run hello.go You should see Hello, world! printed in the console. If you look inside the directory after running the go run command, you see that no binary has been saved there; the only file in the directory is the hello.go file we just created. You might be thinking: I thought Go was a compiled language. What’s going on? The go run command does in fact compile your code into a binary. However, the binary is built in a temporary directory. The go run command builds the binary, executes the binary from that temporary directory, and then deletes the binary after your program finishes. This makes the go run command useful for testing out small programs or using Go like a scripting language.
📄 Page
19
TIP Use go run when you want to treat a Go program like a script and run the source code immediately. go build Most of the time you want to build a binary for later use. That’s where you use the go build command. On the next line in your terminal, type: go build hello.go This creates an executable called hello (or hello.exe on Windows) in the current directory. Run it and you unsurprisingly see Hello, world! printed on the screen. The name of the binary matches the name of the file or package that you passed in. If you want a different name for your application, or if you want to store it in a different location, use the -o flag. For example, if we wanted to compile our code to a binary called “hello_world,” we would use: go build -o hello_world hello.go TIP Use go build to create a binary that is distributed for other people to use. Most of the time, this is what you want to do. Use the -o flag to give the binary a different name or location. Getting Third-Party Go Tools
📄 Page
20
While some people choose to distribute their Go programs as pre- compiled binaries, tools written in Go can also be built from source and installed into your Go workspace via the go install command. Go’s method for publishing code is a bit different than most other languages. Go developers don’t rely on a centrally hosted service, like Maven Central for Java or the NPM registry for JavaScript. Instead, they share projects via their source code repositories. The go install command takes an argument, which is the location of the source code repository of the project you want to install, followed by an @ and the version of the tool you want (if you just want to get the latest version, use @latest). It then downloads, compiles, and installs the tool into your $GOPATH/bin directory. Let’s look at a quick example. There’s a great Go tool called hey that load tests HTTP servers. You can point it at the website of your choosing or an application that you’ve written. Here’s how to install hey with the go install command: $ go install github.com/rakyll/hey@latest go: downloading github.com/rakyll/hey v0.1.4 go: downloading golang.org/x/net v0.0.0-20181017193950-04a2e542c03f go: downloading golang.org/x/text v0.3.0 This downloads hey and all of its dependencies, builds the program, and installs the binary in your $GOPATH/bin directory. NOTE As we’ll talk about in “Module Proxy Servers”, the contents of Go repositories are cached in proxy servers. Depending on the repository and the values in your GOPROXY environment variable, go install may download from a proxy or directly from a repository. If go install downloads directly from a repository, it relies on command-line tools being installed on your computer. For example, you must have Git installed to download from GitHub.