Practical Go. Amit Saha
Чтение книги онлайн.
Читать онлайн книгу Practical Go - Amit Saha страница 10
$
symbol. However, you also should be able to run the same command on Windows. Wherever I have asked you to execute a command to create a directory or copy a file, I have indicated the commands for both Linux/macOS and Windows, where they are different.
Terms
I have used some terms throughout the book that may be best clarified here to avoid ambiguity and set the right expectations.
Robustness and Resiliency
Both terms, robustness and resiliency, express the ability of an application to handle unexpected scenarios. However, these terms differ in their expected behavior under these circumstances as compared to their normal behavior. A system is robust if it can withstand unexpected situations and continue to function to some degree. This will likely be suboptimal behavior, as compared to normal behavior. On the other hand, a system is resilient if it continues exhibiting its normal behavior, potentially taking a finite amount of time before being able to do so. I put forward the following examples from the book to illustrate the difference.
In Chapter 2, you will learn to enforce time-outs for command-line application functionality that is executing a user-specified program. By enforcing time-outs, we avoid the scenario where the application continues to hang indefinitely because of bad user output. Since we configure an upper bound on how long we want to allow the user-specified command to be executed, we will exit with an error when this duration expires before the command could be completed. This is not the normal behavior of the application—that we should wait for the command to complete—but this suboptimal behavior is necessary to allow the application to recover from an unexpected situation, such as the user-specified command taking longer than expected. You will find similar examples throughout, notably when sending or receiving network requests in Chapters 4, 7, 10, and 11. We will refer to these techniques as introducing robustness in our applications.
In Chapter 10, you will learn to handle transient failures in your gRPC client applications. You will write your applications in a manner in which they can tolerate temporary failures that are likely to be resolved soon. We refer to this as introducing resilient behavior in our applications. However, we also introduce an upper time limit, which we allow to resolve the potentially temporary failure. If this time limit is exceeded, we consider that the operation cannot be completed. Thus, we introduce robustness as well.
To summarize, resiliency and robustness both aim to handle unexpected situations in our applications, and this book uses these terms to refer to such techniques.
Production Readiness
I use the term production readiness in the book as all steps that you should think about as you develop your application but before you deploy it to any kind of a production environment. When the production environment is your own personal server where you are the only user of your application, the techniques that you will learn will likely be sufficient. If the production environment means that your application will perform critical functionality for your users, then the techniques in this book should be the absolute baseline and a starting point. Production readiness consists of a vast body of often domain-specific techniques across various dimensions—robustness and resiliency, observability, and security. This book shows you how to implement a small subset of these topics.
Reference Documentation
The code listings in the book use various standard library packages and a few third-party packages. The descriptions of the various functions and types are limited to the contextual usage. Knowing where to look when you want to find out more about a package or function is important to get the most out of the book. The key reference documentation for all standard library packages is https://pkg.go.dev/std
. When I import a package as net/http
, the documentation for that package will be found at the path https://pkg.go.dev/net/http
. When I refer to a function such as io.ReadAll()
, the function reference is the package io
's documentation at https://pkg.go.dev/io
.
For third-party packages, the documentation is available by going to the address https://pkg.go.dev/<import path>
. For example, the Go gRPC package is imported as google.golang.grpc
. Its reference documentation is available at https://pkg.go.dev/google.golang.org/grpc
.
Go Refresher
I recommend going through the topics in “A Tour of Go,” at https://tour.golang.org/list
, to serve as a refresher of the various features that we will be using to implement programs in the book. These include for loops, functions, methods, struct and interface types, and error values. Additionally, I want to highlight the key topics that we will use extensively, along with references to learn more about them.
Struct Type
We will be using struct types defined by the standard library and third-party packages, and we will also be defining our own. Beyond defining objects of struct types, we will be working with types that embed other types—other struct types and interfaces. The section “Embedding” in the “Effective Go” guide (https://golang.org/doc/effective_go#embedding
) describes this concept. We will also be making use of anonymous struct types when writing tests. This is described in this talk by Andrew Gerrand, “10 things you (probably) don't know about Go”: https://talks.golang.org/2012/10things.slide#1
.
Interface Type
To use the various library functions and to write testable applications, we will be making extensive use of interface types. For example, we will be making extensive use of alternative types that satisfies the io.Reader
and io.Writer
interfaces to write tests for applications that interface with the standard input and output.
Learning to define a custom type that satisfies another interface is a key step to writing Go applications, where we plug in our functionality to work with the rest of the language. For example, to enable sharing data across HTTP handler functions, we will define our own custom type implementing the http.Handler
interface.
The section on interfaces in “A Tour of Go,” https://tour.golang.org/methods/9
, is useful to get a refresher on the topic.
Goroutines and Channels
We will be using goroutines and channels to implement concurrent execution in our applications. I recommend going through the section on Concurrency in “A Tour of Go”: https://tour.golang.org/concurrency/1
. Pay special attention to the example use of select statements to wait on multiple channel communication operations.
Testing