Easiest way to check if a program is statically compiled:
file hello_world
TLDR: If you're not using cgo, just:
CGO_ENABLED=0 go build
In general, cgo makes static linking a bit more challenging. There's a few ways to work around these issues:
avoidance
There are two packages in the standard library that use cgo:
os/user
contains cgo code to use the standard C library to map user and group
ids to user and group names. There is also a Go implementation which parses
/etc/passwd
and /etc/group
. The advantage of using the C library is that it
can also get user information from LDAP or NIS. If you don’t use that – most
people don’t – then there is no real difference.
net
can use the C standard library to resolve domain names, but by default it
uses the Go client. The C library has a few more features (e.g. you can
configure getaddrinfo()
with /etc/gai.conf
) and some platforms don’t have a
resolv.conf
(e.g. Android), but for most cases the Go library should work
well.
Your binary will not be statically linked if your program imports one of those
two packages, either directly through a dependency. Especially the net
one is
quite common.
You can use the osusergo and netgo build tags to skip building the cgo parts:
$ go build -tags osusergo
$ go build -tags netgo
$ go build -tags osusergo,netgo
For simple cases where you don’t use any other cgo code it’s probably easier to
just disable cgo, since the cgo code is protected with +build cgo
:
CGO_ENABLED=0 go build
passing options to the c linker
What if we want to use the cgo versions of the above? Or what if we want to use
a cgo package such as SQLite? In those cases you can tell the C linker to
statically link with -extldflags
:
go build -ldflags="-extldflags=-static"