Common libraries
source ↗Common libraries
Flags
Go programs in the Google codebase use an internal variant of the
standard flag package. It has a similar interface but interoperates well
with internal Google systems. Flag names in Go binaries should prefer to use
underscores to separate words, though the variables that hold a flag’s value
should follow the standard Go name style (mixed caps). Specifically, the flag
name should be in snake case, and the variable name should be the equivalent
name in camel case.
// Good:
var (
pollInterval = flag.Duration("poll_interval", time.Minute, "Interval to use for polling.")
)
// Bad:
var (
poll_interval = flag.Int("pollIntervalSeconds", 60, "Interval to use for polling in seconds.")
)
Flags must only be defined in package main or equivalent.
General-purpose packages should be configured using Go APIs, not by punching through to the command-line interface; don’t let importing a library export new flags as a side effect. That is, prefer explicit function arguments or struct field assignment or much less frequently and under the strictest of scrutiny exported global variables. In the extremely rare case that it is necessary to break this rule, the flag name must clearly indicate the package that it configures.
If your flags are global variables, place them in their own var group,
following the imports section.
There is additional discussion around best practices for creating complex CLIs with subcommands.
See also:
- Tip of the Week #45: Avoid Flags, Especially in Library Code
- Go Tip #10: Configuration Structs and Flags
- Go Tip #80: Dependency Injection Principles
Logging
Go programs in the Google codebase use a variant of the standard log
package. It has a similar but more powerful interface and interoperates well
with internal Google systems. An open source version of this library is
available as package glog, and open source Google projects may use that, but
this guide refers to it as log throughout.
Note: For abnormal program exits, this library uses log.Fatal to abort
with a stacktrace, and log.Exit to stop without one. There is no log.Panic
function as in the standard library.
Tip: log.Info(v) is equivalent log.Infof("%v", v), and the same goes for
other logging levels. Prefer the non-formatting version when you have no
formatting to do.
See also:
- Best practices on logging errors and custom verbosity levels
- When and how to use the log package to stop the program
Contexts
Values of the context.Context type carry security credentials, tracing
information, deadlines, and cancellation signals across API and process
boundaries. Unlike C++ and Java, which in the Google codebase use thread-local
storage, Go programs pass contexts explicitly along the entire function call
chain from incoming RPCs and HTTP requests to outgoing requests.
When passed to a function or method, context.Context is always the first
parameter.
func F(ctx context.Context /* other arguments */) {}
Exceptions are:
-
In an HTTP handler, where the context comes from
req.Context(). -
In streaming RPC methods, where the context comes from the stream.
Code using gRPC streaming accesses a context from a
Context()method in the generated server type, which implementsgrpc.ServerStream. See gRPC Generated Code documentation. -
In test functions (e.g.
TestXXX,BenchmarkXXX,FuzzXXX), where the context comes from(testing.TB).Context(). -
In other entrypoint functions (see below for examples of such functions), use
context.Background().- In binary targets:
main - In general purpose code and libraries:
init
- In binary targets:
Note: It is very rare for code in the middle of a callchain to require creating a base context of its own using
context.Background(). Always prefer taking a context from your caller, unless it’s the wrong context.You may come across server libraries (the implementation of Stubby, gRPC, or HTTP in Google’s server framework for Go) that construct a fresh context object per request. These contexts are immediately filled with information from the incoming request, so that when passed to the request handler, the context’s attached values have been propagated to it across the network boundary from the client caller. Moreover, these contexts’ lifetimes are scoped to that of the request: when the request is finished, the context is cancelled.
Unless you are implementing a server framework, you shouldn’t create contexts with
context.Background()in library code. Instead, prefer using context detachment, which is mentioned below, if there is an existing context available. If you think you do needcontext.Background()outside of entrypoint functions, discuss it with the Google Go style mailing list before committing to an implementation.
The convention that context.Context comes first in functions also applies to
test helpers.
// Good:
func readTestFile(ctx context.Context, t *testing.T, path string) string {}
Do not add a context member to a struct type. Instead, add a context parameter to each method on the type that needs to pass it along. The one exception is for methods whose signature must match an interface in the standard library or in a third party library outside Google’s control. Such cases are very rare, and should be discussed with the Google Go style mailing list before implementation and readability review.
Note: Go 1.24 added a (testing.TB).Context() method. In tests, prefer
using (testing.TB).Context() over context.Background() to provide the
initial context.Context used by the test. Helper functions, environment or
test double setup, and other functions called from the test function body that
require a context should have one explicitly passed.
Code in the Google codebase that must spawn background operations which can run after the parent context has been cancelled can use an internal package for detachment. Follow issue #40221 for discussions on an open source alternative.
Since contexts are immutable, it is fine to pass the same context to multiple calls that share the same deadline, cancellation signal, credentials, parent trace, and so on.
See also:
Custom contexts
Do not create custom context types or use interfaces other than
context.Context in function signatures. There are no exceptions to this
rule.
Imagine if every team had a custom context. Every function call from package p
to package q would have to determine how to convert a p.Context to a
q.Context, for all pairs of packages p and q. This is impractical and
error-prone for humans, and it makes automated refactorings that add context
parameters nearly impossible.
If you have application data to pass around, put it in a parameter, in the
receiver, in globals, or in a Context value if it truly belongs there.
Creating your own context type is not acceptable since it undermines the ability
of the Go team to make Go programs work properly in production.
crypto/rand
Do not use package math/rand to generate keys, even throwaway ones. If
unseeded, the generator is completely predictable. Seeded with
time.Nanoseconds(), there are just a few bits of entropy. Instead, use
crypto/rand’s Reader, and if you need text, print to hexadecimal or base64.
// Good:
import (
"crypto/rand"
// "encoding/base64"
// "encoding/hex"
"fmt"
// ...
)
func Key() string {
buf := make([]byte, 16)
if _, err := rand.Read(buf); err != nil {
log.Fatalf("Out of randomness, should never happen: %v", err)
}
return fmt.Sprintf("%x", buf)
// or hex.EncodeToString(buf)
// or base64.StdEncoding.EncodeToString(buf)
}
Note: log.Fatalf is not the standard library log. See [#logging].