hendry
hendry

Reputation: 10813

Why is CGO_ENABLED=1 default?

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

Answers (1)

colm.anseo
colm.anseo

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:

  • net: see DNS Name Resolution
  • os/users:
    • CGO_ENABLED=1 uses the native OS (e.g. on Linux nsswitch) for ID lookup
    • CGO_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 of

Deployment

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

Related Questions