Reputation: 10813
CGO_ENABLED=1 I believe is the current default which means that it depends on GLIBC which can have breaking changes between updates & distributions.
CGO_ENABLED=0 is the workaround for creating static standalone binaries, so why isn't this the default?
Upvotes: 21
Views: 16481
Reputation: 22027
In general, CGO_ENABLED=1
leads to faster, smaller builds & runtimes - as it can dynamically load the host OS's native libraries (e.g. glibc
, DNS resolver etc.) - when running on the build OS. This is ideal for local rapid development. For deployment, CGO_ENABLED=1
may not be practical or even possible - when considering the deployment hosting OS.
If you're purely using the standard library, they you may not necessarily need CGO enabled. In certain standard libraries behavior will different if using a pure-Go version (CGO_ENABLED=0
) or a CGO-enabled version:
CGO_ENABLED=1
uses the native OS (e.g. on Linux nsswitch
) for ID lookupCGO_ENABLED=0
uses a basic Go implementation (e.g. reads from /etc/passwd
) - which does not include other ID registries the host may be aware ofDeployment
While a CGO_ENABLED=1
binary may be smaller in size, it relies on delivering a host OS too. Comparing Docker images:
ubuntu:20.04
is 73.9MB (glibc
: GNU-libc)alpine:3.12.1
is 5.57MB (musl
libc)so adding an OS (even a minimal one) adds this extra baggage. alpine
looks attractive in its minimal size - but its libc
may not be compatible with packages that rely on glibc
.
CGO_ENABLED=0
is, however, ideal for scratch docker image deployments - as no host OS needs to be bundled.
However, if your application imports a package with C-code (e.g. go-sqlite3) then your build must enable CGO.
Upvotes: 30