Skip to content
shellhacks.dev
Go

Build a static binary

Build a statically linked Go binary with CGO_ENABLED=0. Programs that import net link to libc by default when a C compiler is present, which breaks on Alpine.

1 min read
Summarize in AI

A Go binary built on Debian crashes on Alpine or in a scratch image with "not found", because it depends on a C library the target does not have.

main.goGo
package main

import (
	"fmt"
	"net"
)

func main() {
	fmt.Println(net.ParseIP("10.0.0.1"))
}
Shell
go build -o dynamic main.go
CGO_ENABLED=0 go build -o static main.go
ldd dynamic | head -2
ldd static
Text
	linux-vdso.so.1 (0x0000ffff94e06000)
	libc.so.6 => /lib/aarch64-linux-gnu/libc.so.6 (0x0000ffff94c10000)
	not a dynamic executable

The net and os/user packages have a cgo implementation that calls the C resolver, and the go tool uses it whenever a C compiler is found and CGO_ENABLED is not 0. The first binary therefore links against libc. Setting the variable to 0 selects the pure Go implementation, as the cgo documentation describes, and ldd confirms the second binary needs nothing.

With cgo off, the DNS resolver and user lookups use the pure Go code, which can behave differently from the system resolver with unusual nsswitch.conf setups. Libraries that need C, like SQLite drivers based on the C source, will not build. Output here is from Go 1.19 on Debian 12.

Share

More snippets

Go

Exit with a status

Exit with a status using os.Exit(n). It ends the program at once and skips every deferred call, so cleanup in defer is not run before the exit.

1 min read
Go

Raise the scanner line limit

Raise the line limit of bufio.Scanner with Buffer(make([]byte, 0, 64*1024), max). Lines over 64 KB otherwise stop the scan with token too long.

1 min read
Go

Set a timeout for a command

Stop a command that takes too long with exec.CommandContext and context.WithTimeout. In Go 1.19 a shell's child can keep Output() waiting past the deadline.

2 min read

Get new posts by email

One email when a new post is published. No spam.

Unsubscribe in one click. No spam, ever.