Go

Basics

  • If you receive "cannot find package" errors when importing a package, either export GO111MODULE=on or create a module with go mod init $MODULE

Hello World

helloworld.go:

package main

import "fmt"

func main() {
    fmt.Println("Hello, World!")
}

Run:

$ go run helloworld.go 
Hello, World!

Thread Dump

Built-in thread dump

By default, Go handles the SIGQUIT signal by printing a stack trace to stdout/stderr although then it kills itself:

A SIGQUIT, SIGILL, SIGTRAP, SIGABRT, SIGSTKFLT, SIGEMT, or SIGSYS signal causes the program to exit with a stack dump.

Manually generated thread dump

A thread dump may be manually generated by first calling pprof.Lookup on the goroutine profile and then writing that to a file with Profile.WriteTo.

Heap Dump

Manually generated heap dump

A heap dump may be manually generated by calling debug.WriteHeapDump.

Analyzing a Heap Dump from a Core Dump

If you have a core dump, its heap may be analyzed with viewcore.

However, viewcore requires that the executable does not have stripped symbols.

In addition, viewcore is not very actively maintained and there are known issues as of this writing, so, in general, it's better to use debug.WriteHeapDump instead if possible.

Building viewcore
git clone https://github.com/golang/debug
cd debug
CGO_ENABLED=0 go build golang.org/x/debug/cmd/viewcore
Running viewcore
./viewcore core.dmp --exe targetexe
viewcore commands
Available Commands:
  breakdown   print memory use by class
  goroutines  list goroutines
  help        Help about any command
  histogram   print histogram of heap memory use by Go type
  html        start an http server for browsing core file data on the port specified with -port
  mappings    print virtual memory mappings
  objects     print a list of all live objects
  objgraph    dump object graph (dot)
  overview    print a few overall statistics
  reachable   find path from root to an object
  read        read a chunk of memory
Additional debugging

If additional debugging information is required, consider compiling the target program without optimizations and inlining:

make build GOFLAGS="-gcflags=all='-N -l'"

Signal processing

Go allows a program to handle various POSIX signals:

The functions in this package allow a program to change the way Go programs handle signals.

It also applies to some signals that otherwise cause no action: SIGUSR1, SIGUSR2

Therefore, it's valuable for any Go program to add a SIGUSR1 handler to write a thread dump and a SIGUSR2 handler to write a heapdump. For example:

usr1 := make(chan os.Signal, 1)
signal.Notify(usr1, unix.SIGUSR1)

usr2 := make(chan os.Signal, 1)
signal.Notify(usr2, unix.SIGUSR2)

go func() {
    for {
        select {
        case <- usr1:
            f, err := os.Create("threaddump_" + time.Now().Format(time.RFC3339) + ".txt")
            if err != nil {
                // TODO handle error
                continue
            }
            err = pprof.Lookup("goroutine").WriteTo(f, 2)
            if err != nil {
                // TODO handle error
                continue
            }
        case <- usr2:
            f, err := os.Create("heapdump_" + time.Now().Format(time.RFC3339) + ".bin")
            if err != nil {
                // TODO handle error
                continue
            }
            debug.WriteHeapDump(f.Fd())
        }
    }
}()

Stripping symbols

Though not recommended for maintainability, it is common to use the -s -w link options; for example:

go build -ldflags="-s -w"

This strips debugging symbols from the final executable:

-s
  Omit the symbol table and debug information.
-w
  Omit the DWARF symbol table.

Although stripping symbols is done for non-debug builds of some common executables such as kubelet, unless the size difference is very large or there are security concerns about reverse engineering, it is generally a net positive for maintenance to retain symbols by removing the -s -w link options. This will allow crash debugging, viewcore, some native stack walking tools, and it is not expected to have a performance impact to retain symbols.