Introducing Go - Manning Publications

MEAPEdition
ManningEarlyAccessProgram
GoinAction
Version7
Copyright2015ManningPublications
FormoreinformationonthisandotherManningtitlesgoto
www.manning.com
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
Welcome
Thank you for purchasing the MEAP for Go in Action. We’ve been writing this book in
one form or another for almost four years now, so we’re very excited to release it to you:
our intrepid early adopter. This book was written for an intermediate level developer who
has some experience with other programming languages and is curious about Go.
Our goal in writing Go in Action is not just to introduce you to the Go language, but to
share our experiences using Go in high-volume production environments. As the book
progresses, we’ll show you patterns for success and hopefully debunk some anti-patterns
too.
Our initial release will include the first two chapters, which are focused on getting you
acquainted with this new programming language. Chapters 1 and 2 will give you an
overview of the language and the workflow that you’ll use as a Go developer. By the end of
Chapter 2, you will be comfortable reading and understanding most Go code.
Most of the chapters in this book will be broken into two parts: Part I will teach you the
concepts that power the language, and Part II will show you how to apply those concepts in
your projects.
You should be getting updates to this book every two to three weeks. Sometimes we’ll
release the chapters with only Part I, and release Part II a little later; sometimes we’ll release
whole chapters at once. We’re counting on your feedback to help us shape this book into an
indispensable tool for professional developers who want to become proficient with Go.
Please join us on the Manning Author Online Forum. We’ll be reading your comments,
providing help and feedback, and using your suggestions to make the book better before it is
published.
The source code for the examples in the book is available at
https://github.com/goinaction/code Feel free to download and play along! We look forward
to your feedback as we finalize this book.
Brian Ketelsen
William Kennedy
Erik St. Martin
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
brief contents
1 Introducing Go
2 Go Quick Start
3 Packaging and Tooling
4 Arrays, Slices and Maps
5 Building User Defined Types
6 Concurrency
7 Concurrency Patterns
8 Standard Library
9 Writing Network Applications in Go
10 Debugging and Testing Go Programs
11 Reflection
12 Making Your Applications More Performant
13 Interoperating with C Libraries
14 Using Go for Devops
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
1
1
Introducing Go
In this chapter
The Case for Go
Using the Go Tools
Prerequisites - Things you should know before reading this chapter
You should be familiar with a command prompt or shell
You should have Go installed according to the guidelines in the
preface of this book
You should be familiar with at least one other programming
language
Computers have evolved, but programming languages haven't kept the same pace
of evolution. The cell phone you carry probably may have more CPU cores than
the first computer you used. High powered servers now have 64, 128, or even more
cores, but we're still programming using the techniques we've been using for a
single core.
The art of programming has evolved too. Most programs aren't written by a
single developer any more, they're written by teams of people sitting in different
time zones, working at different times of the day. Large projects are broken up into
smaller pieces and assigned to programmers who then deliver their work product
back to the team in the form of a library or package that can be used across an
entire suite of programs.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
2
Today's programmers and companies believe more and more in the power of
Open Source Software. Go is a programming language that makes sharing code
easy. Go ships with tools that make it simple to use packages written by others, and
Go makes it easy to share your own packages too.
In this chapter you'll see how Go is different from other programming
languages. Go rethinks the traditional Object Oriented development you might be
used to while still providing an efficient means for code reuse. Go makes it easier
for you to effectively use all of the cores on your expensive server, and Go takes
away the penalty of compiling a very large project.
As you read this chapter, you'll get a feeling for the many decisions that shaped
the creation of Go, from its concurrency model to its lightning fast compiler. You'll
appreciate the tools that ship with Go to make your life as a developer easier.
You'll see why so many developers are choosing Go when they start up that new
project.
1.1 Why Do We Need Another Programming Language?
It isn't easy to pick a programming language when you're starting a new project, or
even picking a platform for your team. Every programming language comes with a
set of tradeoffs that make the decision a difficult one. Let's look at some of the
more obvious tradeoffs you will find as you look at new languages.
1.1.1 Choosing Static vs. Dynamic Languages
If you've ever spent time writing code using a dynamic language, you'll know why
people love them. It's so easy to throw together a script that manipulates some data
without formally worrying about the data types. This flexibility comes with some
grief. You can't always presume that the data you receive is the data you're
expecting, and you can get some pretty crazy results from dynamic languages
when you feed them unexpected data. The solution is writing more code and lots of
tests.
Conversely, static languages give you type safety which can frustrate you with
repetition. Code, Compile, Test... Code, Compile, Test... Lather, Rinse, Repeat!
Compiling is a productivity killer. But with compiled languages, deploying your
compiled binaries is a breeze and the burden of testing bizarre edge cases is a little
more palatable.
We need something better that provides the benefits of dynamic and interpreted
languages with the speed and safety of static and compiled languages.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
3
1.1.2 How Will Your Language Handle Concurrency
Very few programming languages have given more than a passing thought to
concurrency. Some dynamic languages like Ruby and Python implement a Global
Interpreter Lock into their runtimes to ensure thread-safety and mitigate
race-conditions, it comes at the cost of reducing performance, as the interpreter can
only be executing in one thread at a time. Other languages, like Java, have the
primitives needed for concurrency but often require tons of boilerplate code to
write concurrent applications properly.
We need a language that makes concurrency a first-class citizen.
1.1.3 Are The Batteries Included?
One of the best gauges to determine the utility of a programming language is how
much you can get done without using external libraries. In many languages, it's
hard to do anything beyond simple text manipulation without resorting to installing
gems, eggs, or CPAN modules. And forget about trying to do some serious work
like creating a network service without finding, downloading, testing and learning
some third party code.
Wouldn't it be nice if there was a language where nearly all the heavy lifting
was already done for you?
1.2 Solving Modern Programming Challenges With Go
The Go team went to great lengths to solve the problems facing software
developers today. Developers have to make an uncomfortable choice between
rapid development and performance when choosing a language for their projects.
Some languages like C or C++ offer fast execution, while other languages like
Ruby or Python offer rapid development. Go bridges these competing worlds and
offers a high performance language with features that make development fast.
As you explore Go, you'll find well planned features and concise syntax. As a
language, Go is defined not only by what it includes, but by what it doesn't include.
Go has a concise syntax with very few keywords to memorize. Go has a compiler
that's so fast, you might not notice it at all. As a developer you will spend
significantly less time waiting for your project to build. Because of the built-in
concurrency features of Go, your software will scale to use the resources available
without forcing you to use special threading libraries. Go uses a simple and
effective type system that takes much of the overhead out of object-oriented
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
4
development and lets you focus on code reuse. Go also has a garbage collector, so
you don't have to manage your own memory. Let's look quickly at these key
features of Go.
1.2.1 Programs Compile Quickly
Compiling a large application in C or C++ takes more time than getting a cup of
coffee. Figure 1.1 is an XKCD classic excuse for messing around in the office. Go
offers lightning quick compiles by using a smart compiler and simplified
dependency resolution algorithms. When you build a Go program, the compiler
only needs to look at the libraries that you directly include, rather than traversing
the dependencies of all the libraries that are included in the entire dependency
chain like Java, C and C++. Consequently, many Go applications compile in under
a second. The entire Go source tree compiles in just under twenty seconds on
modern hardware.
Figure 1.1 Working Hard? (via XKCD)
Writing applications in dynamic languages makes you productive quickly
because there are no intermediate steps between writing code and executing that
code. The tradeoff is that dynamic languages don't offer the type safety that static
languages do, and often need a very comprehensive test suite to avoid discovering
incorrect type bugs at runtime.
Imagine writing a large application in a dynamic language like Javascript and
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
5
you come across a function that expects to receive a field called ID. Is that an
integer, a string, a UUID? The only way to find out is to look at the source if you
have it, or try to execute the function with a number or a string and see what
happens. In Go, you wouldn't spend a second of time wondering, because the
compiler will catch type differences for you.
1.2.2 Concurrency is Built In
One of the hardest things to do as a programmer is to write an application that
effectively uses the available resources of the hardware running it. Modern
computers have many cores, but most programming languages don't have effective
tools for utilizing those additional resources easily. They often require a lot of
thread synchronization code, which is prone to errors.
Go's concurrency support is one of its strongest features. Goroutines are like
threads, but use far less memory and require much less code to implement.
Channels are typed memory queues that let you send messages between goroutines.
This facilitates a programming model where you send data between goroutines,
rather than letting the goroutines fight to use the same data. Let's look at these
features in more detail now.
GOROUTINES
Goroutines are functions that run concurrently with other goroutines, including the
entry point of your program. In other languages, you would use threads to
accomplish the same thing, but in Go, many goroutines execute on a single thread.
For example, if you write a web server and you want to handle different web
requests simultaneously, you would have to write a lot of extra code to use threads
in C or Java, but Go's net/http library has concurrency built in using goroutines.
Each inbound request automatically processes on it's own goroutine. Goroutines
use less memory than threads and the Go runtime will automatically schedule the
execution of goroutines from a configurable pool of threads. This makes your
application much more efficient with significantly less development effort.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
6
Figure 1.2 Many Goroutines Execute On A Single OS Thread
If you want to execute some code concurrently while you move on to
accomplish other things, a goroutine is perfect for the job. Here is a quick example:
func logError(errorMessage string){
... some error logging code here
}
// Elsewhere in your code after you've discovered an error.
go logError("something dire happened")
That keyword go is all you need to launch the logError() function as a
goroutine and be run concurrently with other goroutines. This means you can
continue executing the rest of your application while the logging happens
concurrently, which often results in greater perceived performance for your end
users. Goroutines have minimal overhead, and it isn't uncommon to spawn tens of
thousands of them without incurring memory bloat or processing overhead. We'll
explore goroutines and concurrency more in-depth in Chapter 6.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
7
CHANNELS
Channels are typed memory queues that act as a pipeline to enable safe data
communication between goroutines. When used correctly, channels help you to
avoid problems typically seen in programming languages that allow shared
memory access.
The hardest part of concurrency is ensuring that your data is not unexpectedly
modified by concurrently running processes, threads, or goroutines. When multiple
threads change the same data without locks or synchronization, heartache always
follows. When you have global variables and shared memory, you are required to
use complicated mutexes or locks to prevent unsynchronized changes to the same
variables.
Channels help to solve this problem by providing a pattern that makes data safe
from concurrent modification. Channels help to enforce the pattern that only one
goroutine should modify the data at any time. You can see an example of this flow
in Figure 1.3, where channels are used to send data between several running
goroutines. Imagine an application where many different processes need to know
about or modify data sequentially. Using goroutines and channels, you can model
this process safely.
Figure 1.3 Using Channels To Safely Pass Data Between Goroutines
Each goroutine in Figure 1.3 has exclusive control of the data it receives on a
channel. The goroutine can modify the data, or act upon it, then send it down the
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
8
pipeline to the next goroutine for processing. Because of the guarantees that
channels provide, there are no locks or mutexes required to safely modify the data.
1.2.3 Go's Type System Enables Code Reuse
Go rethinks traditional object orientation for a flexible hierarchy-free type system
that enables code reuse with minimal refactoring overhead. It is still
object-oriented development, but without the headaches. If you've ever spent a
week trying to determine how to set up your abstract classes and interfaces in a
complex Java or C++ program, you'll appreciate the simplicity of Go's type system.
Go developers simply embed types to re-use functionality in a design pattern called
Composition. Other languages use composition, but it is often deeply tied to
inheritance, which can make it complicated and difficult to use. Your types in Go
are composed of smaller types, which is in contrast to traditional inheritance based
models.
In addition, Go has a unique interface implementation that allows you to model
actions, rather than modeling types. You don't need to declare that you are
implementing an interface in Go, the compiler does the hard work of determining
whether your type satisfies the interfaces you are using. Many interfaces in Go's
standard library are very small, exposing only a few functions. In practice this
takes some time to get used to, especially if you've been writing in very strong
object-oriented languages like Java.
TYPES ARE SIMPLE
Go has built-in types like int and string as well as user-defined types. A typical
user-defined type in Go will have typed fields to store data. If you've seen structs
in C, Go's user-defined types look and operate similarly. However, types may also
declare methods that operate on that data. But rather than building a long
inheritance structure---Sedan extends Car extends Vehicle---Go developers build
small types---Wheel and Door---and embed them into larger ones. Figure 1.4
demonstrates the difference between inheritance and composition.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
9
Figure 1.4 Inheritance Vs. Composition
GO INTERFACES MODEL SMALL BEHAVIORS
Interfaces allow you to express the capabilities of a type. If a type implements an
interface, it means that a type has a specific set of capabilities. You don't even need
to declare that you're implementing an interface, you just need to write the
implementation. Other languages call this Duck Typing -- if it quacks like a duck,
then it can be a duck-- and Go does it well. In Go, if your type implements the
methods of an interface, it can be used anywhere that interface is expected, no
declaration required.
In a strictly object-oriented language like Java, interfaces are all encompasing.
You're often required to think through a large inheritance chain before you're able
to even start writing code. Here's an example of a java interface:
interface Animal {
public void eat();
public void move();
}
Implementing this interface in Java requires you to create a class that fulfills all
of the promises made in the Animal interface and explicitly declare that you
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
10
implement the interface. In contrast, a Go interface typically represents just a
single action. One of the most common interfaces you will use in Go is the
io.Reader. The io.Reader interface provides a simple way to declare that your type
has data to be read in a way that other functions in the standard library understand.
Here's the definition:
type Reader interface {
Read(p []byte) (n int, err error)
}
To write a type that implements the io.Reader interface, you only need to
implement a Read function that accepts a slice of bytes and returns an integer and
possible error.
This is a radical departure from the interface systems used in other object
oriented programming languages. Go's interfaces are smaller, and more aligned
with single actions. In practice, this allows significant advantages in code reuse.
You can implement an io.Reader on nearly any type that has data available, and
then pass it to any Go function that knows how to read from a Reader. The entire
networking library in Go is built using the io.Reader interface, because it allows
you to separate the network implementation required for each different network
operation from the functionality of your application. It makes interfaces fun,
elegant, and flexible. That same io.Reader enables simple operations with files,
buffers, sockets and any other data source. Using a simple interface allows you to
operate on data efficiently, regardless of the source.
1.2.4 Memory Management Is Easy
Improper memory management causes applications to crash, leak memory and
even crash the operating system. Go has a modern garbage collector that does the
hard work for you. In other systems languages, like C or C++, you need to allocate
a piece of memory before you can use it, then de-allocate it when you're done. If
you fail to do either of these correctly, you'll have program or system crashes. It
isn't easy to track a piece of memory when it is no longer needed; threads and
heavy concurrency make it even harder. When you write code with garbage
collection in mind, Go's garbage collection adds very little overhead to program
execution time, but reduces development effort significantly. Go takes the tedium
out of programming and leaves the bean counting to the accountants.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
11
1.3 Hello, Go
It's much easier to get the feel of a programming language by seeing it in action.
Let's look at the traditional Hello World! application written in Go:
package main
import "fmt"
func main(){
fmt.Println("Hello World")
}
Go programs are organized as packages.
The import statement allows you to use external code. The "fmt" package, in this
case, which is provided by the standard library allows you to format and print data.
The main() function is what gets executed when you run your application - just like
in C.
This sample program prints a familiar phrase on your screen when you run it.
But how should you run it? Without installing Go on your computer, you can use
almost all of Go right from your web browser.
1.3.1 Introducing the Go Playground
There is a tool that allows you to edit and run Go code from your web browser
called the Go Playground. Fire up a web browser and navigate to
http://play.golang.org We'll wait for you. It should look a lot like Figure 1.5:
Figure 1.5 The Go Playground
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
12
The code in the browser window is editable right on the screen. Click the RUN
button and see what happens! The code executes and its output is printed at the
bottom of the screen like Figure 1.6:
Figure 1.6 Output From Go
Playground Shown In Your
Browser Window
You can change the code, for example to make the greeting text in a different
language. Go ahead and change the greeting inside the fmt.Println() function and
hit RUN again. Did you see your new greeting appear?
NOTE
Sharing Go Code
Go developers use the Playground to share code ideas, test
theories, and debug their code, as you soon will too. Every time you
create a new application on the Playground, you can click the
Share button to get a sharable URL that anyone else can open. Try
this one: http://play.golang.org/p/EWIXicJdmz
The Go Playground is the perfect way to demonstrate an idea for a coworker or
friend who is trying to learn something, and it's a great way for you to solicit help
too. On the Go IRC channels, in the Go mailing lists, and countless emails sent
among Go developers, you'll see Go Playground applications being created,
modified, and shared.
1.4 Introducing Kiev
In this YET TO BE WRITTEN SECTION, we'll introduce Kiev, which is a project
that will span many chapters of the book providing real-world examples of Go
code.
1.5 Summary and Best Practices
Go is a modern, garbage-collected language with a workflow that helps you to feel
productive while you are using it, mostly because of the great tools that are
provided with the language, like the go command, a focus on enabling easy
concurrency, and a clean syntax that is easy to remember.
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action
13
Go is modern, fast, and comes with all the batteries included
Go has concurrency built-in
Go uses interfaces as the building blocks of code reuse
©Manning Publications Co. We welcome reader comments about anything in the manuscript - other than typos and
other simple mistakes. These will be cleaned up during production of the book by copyeditors and proofreaders.
https://forums.manning.com/forums/go-in-action