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.

Answer from colm.anseo on Stack Overflow
🌐
Medium
medium.com › @pengcheng1222 › exploring-cgo-enabled-in-go-23cf5cf2fe88
Golang — Exploring CGO_ENABLED in Go | by Allen Ning | Medium
November 20, 2024 - When CGO_ENABLED is set to 1, Go programs typically use dynamic linking for C libraries. This means the Go binary relies on shared library files present on the target system at runtime, leading to smaller binaries compared to static linking.
Discussions

What is the consequence of using CGO_ENABLED=0?

With CGO_ENABLED=0 you got a staticaly-linked binary (see: https://en.wikipedia.org/wiki/Static_build) so it will run without any external dependencies (you can buld your dockers from 'scratch' image) Like that: https://github.com/s0rg/microapp/blob/master/Dockerfile

More on reddit.com
🌐 r/golang
33
41
September 5, 2021
go - When using CGO_ENABLED is must and what happens - Stack Overflow
Why does CGO_ENABLE make a such impact on virtual memory? the compiler of the "reference" Go implementation (historically dubbed "gc"; that one, available for download from the main site) by default produces statically-linked binaries. This means, such binaries rely only on the so-called "system ... More on stackoverflow.com
🌐 stackoverflow.com
What is the difference between a binary built with CGOENABLED=0 from the default mode?
I was facing a issue accessing a golang binary inside an alpine container. Aparently the use of some C libraries was lacking from my binary I suppose. Alpine /bin/sh couldn’t find my app binary as a ENTRYPOINT for a Dockerfile. I managed to fix it adding to the go build command the following ... More on forum.golangbridge.org
🌐 forum.golangbridge.org
0
0
February 2, 2023
make.bash: clarify that CGO_ENABLED=0 sets default into resulting compiler
What version of Go are you using (go version)? $ go version 1.17.7 Does this issue reproduce with the latest release? Yes. What did you do? Ran CGO_ENABLED=0 ./make.bash. What did you expect to see... More on github.com
🌐 github.com
8
February 21, 2022
🌐
Go Packages
pkg.go.dev › cmd › cgo
cgo command - cmd/cgo - Go Packages
April 7, 2026 - The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling as well as when the CC environment variable is unset and the default C compiler (typically gcc or clang) cannot be found on the system PATH.
🌐
Reddit
reddit.com › r/golang › what is the consequence of using cgo_enabled=0?
r/golang on Reddit: What is the consequence of using CGO_ENABLED=0?
September 5, 2021 -

Is it a bad idea to set this environment variable to 0? From what I read, setting it to 1 means there should be a gcc compiler installed in the working system. Is this a correct interpretation? Why is it 1 by default?

I was trying to containerise my go application using the below docker file:

FROM golang:latest as builder

ENV GOOS=linux

COPY ./ /go/src/hello_world

WORKDIR /go/src/hello_world

RUN go build .

FROM alpine:latest

WORKDIR /usr/home

COPY --from=builder /go/src/hello_world/hello_world /usr/home

ENTRYPOINT ["./hello_world"]

This was giving me error but based on my findings I put ENV CGO_ENABLED=0 during build and it started working fine.

When is it required to be set to 1 and why did I have to explicitly set to 0 in my case?

P.S. I am very new to go so any resources on this would be appreciated.

Top answer
1 of 2
19

Many things are only available as C libraries, and re-implementing that all in Go would be costly. cgo has its downsides, but it can be a good trade-off. Even the standard library uses it (net for DNS lookups, os/user for user lookups) because it doesn't re-implement 100% of the behaviour in Go.

Cross-compiling C code is still rather hard; you'll need the target architecture's C compiler and toolchain (e.g. CC=aarch64-linux-musl-gccgo build to build an arm64 binary). None of that is installed by default so for most people cgo simply won't work when cross-compiling; they need to take manual steps to set it up first.

cgo often isn't strictly required (like in the net and os/user packages), so disabling it by default seems the most user-friendly option.

But there are no such constraints on the native platform, and it's expected to work by default without any user setup; so why not enable it by default?

2 of 2
8

If you're running on an Alpine image, it is impossible to compile and run Go programs in Alpine images right away. You must disable CGO by setting the environment variable CGO_ENABLED to false (the default value is true).

You can do this either by:

  • Adding go env -w CGO_ENABLED=0 like Robert mentions in his comment or,
  • Setting the env value prefixing it in the go command, e.g.: CGO_ENABLED=0 GOARCH=amd64 GOOS=linux go build -ldflags '-s -w' -tags lambda.norpc -o bin/<YOUR_FUNC>/bootstrap <YOUR_PATH>/main.go

See: https://megamorf.gitlab.io/2019/09/08/alpine-go-builds-with-cgo-enabled/

🌐
Matrix
matrix-org.github.io › go-neb › pkg › C › index.html
cgo - The Go Programming Language
Any .h, .hh, .hpp, or .hxx files ... respectively; those environment variables may include command line options. The cgo tool is enabled by default for native builds on systems where it is expected to work....
🌐
Boinkor
boinkor.net › 2023 › 05 › building-a-golang-program-with-cgo
Building a golang program with cgo - Andreas Fuchs’ Journal
May 25, 2023 - There are two main things you need to do: First, explicitly opt out of disabling the usage of the cgo compiler by setting CGO_ENABLED=1 on the compiler’s process environment. (This defaults to on, but your environment might have it turned off!
Find elsewhere
🌐
GoLinuxCloud
golinuxcloud.com › home › programming › getting started with cgo using visual studio code
Getting started with CGO using Visual Studio Code | GoLinuxCloud
January 7, 2024 - The cgo tool is enabled by default for native builds on systems where it is expected to work. It is disabled by default when cross-compiling.
🌐
Go Forum
forum.golangbridge.org › getting help
What is the difference between a binary built with CGOENABLED=0 from the default mode? - Getting Help - Go Forum
February 2, 2023 - I was facing a issue accessing a golang binary inside an alpine container. Aparently the use of some C libraries was lacking from my binary I suppose. Alpine /bin/sh couldn’t find my app binary as a ENTRYPOINT for a Dockerfile. I managed to fix it adding to the go build command the following variable and flag: CGO_ENABLED=0 -installsufix cgo I managed to fix the issue and the container started to work properly, but I’m not sure why.
🌐
GitLab
gitlab.com › gitlab.org › gitlab-runner › merge requests › !3413
Enable CGO_ENABLED by default in golang-fips compiler (!3413) · Merge requests · GitLab.org / gitlab-runner · GitLab
April 28, 2022 - If CGO_ENABLED=0, then the golang-fips compiler will default to this mode by default, which is counter to the default Golang behavior. Any binary that needs FIPS support would...
🌐
Go
go.dev › src › cmd › cgo › doc.go
- The Go Programming Language
This 116 means that if a header ... find the 119 local version in preference to any other version. 120 121 The cgo tool is enabled by default for native builds on systems where 122 it is expected to work....
🌐
Peng
peng.fyi › post › go-cgo-enabled-default-and-pure-go-alternatives
You probably want to disable cgo: Go's stdlib has pure-Go implementations |
March 25, 2026 - CGO_ENABLED defaults to 1. That means a standard go build produces a binary that links against C libraries (e.g., glibc) at runtime. For many parts of the Go standard library, there is a C-backed implementation and a pure-Go implementation.
🌐
GitHub
github.com › golang › go › issues › 51305
make.bash: clarify that CGO_ENABLED=0 sets default into resulting compiler · Issue #51305 · golang/go
February 21, 2022 - I expected it to produce a compiler (without using cgo) that abides by the documented behavior for cgo. Namely, host builds have cgo enabled by default.
Author   golang
🌐
GitHub
github.com › golang › go › issues › 33673
cmd/go: regression on the default of CGO_ENABLED to 0 for cross builds · Issue #33673 · golang/go
August 15, 2019 - CGO_ENABLED="1" Either the unchanged behavior, or the changed behavior pointed out in the cl description and possibly even in release notes?
Author   golang
🌐
Go Programming Language
tip.golang.org › doc › go1.20
Go 1.20 Release Notes - The Go Programming Language
The go command now disables cgo by default on systems without a C toolchain. More specifically, when the CGO_ENABLED environment variable is unset, the CC environment variable is unset, and the default C compiler (typically clang or gcc) is not found in the path, CGO_ENABLED defaults to 0.
🌐
GitHub
github.com › golang › go › issues › 47251
cmd/go: default to CGO_ENABLED=0 when CC not set and default compiler not found · Issue #47251 · golang/go
July 16, 2021 - Consequently, runtime/cgo, net, os/user, and other packages in std that use cgo by default are stale if the user's C compiler is different than the one used to build the Go binary distribution. It almost always is. If the user does not have a C compiler installed and has not explicitly set CGO_ENABLED=0, go build will fail to build any package that depends on these packages, even if nothing else uses cgo.
Author   golang
🌐
GitHub
github.com › go-task › task › issues › 1272
`CGO_ENABLED` cannot be set to `1` · Issue #1272 · go-task/task
July 21, 2023 - When Task is invoked with CGO_ENABLED=0, the environment variable cannot be set to 1 in the env section of a task declaration. This is reproducible using the following Taskfile. version: 3 tasks: default: env: CGO_ENABLED: 1 cmds: - go env ...
Author   go-task
🌐
GitHub
github.com › golang › go › issues › 12808
build: CGO_ENABLED=0 ./make.bash does not force default in later runs of cmd/go · Issue #12808 · golang/go
October 1, 2015 - I've been trying to figure out how to make my programs build statically by default without specifying -a -installsuffix cgo -ldflags '-extldflags "-static" -s for every project. I've read through #9344, and supposedly the change to make dynamic builds the default is only for released versions of Go.
Author   golang
🌐
ElastiFlow
elastiflow.com › blog › posts › disabling-cgo-to-remove-glibc-dependency
Disable CGO to Remove glibc Dependency for Enhanced Performance
September 22, 2023 - For example, a Go program built on Ubuntu 22.04 will not run on Ubuntu 20.04. To disable CGO, you can set the CGO_ENABLED environment variable to 0 before building your Go program.