为什么 CGO_ENABLED=1 默认?

hen*_*dry 6 go

CGO_ENABLED=1 我相信是当前的默认值,这意味着它取决于 GLIBC,它可以在更新和发行版之间进行重大更改。

CGO_ENABLED=0 是创建静态独立二进制文件的解决方法,为什么这不是默认值?

col*_*tor 6

通常,在CGO_ENABLED=1构建操作系统上运行时,会导致更快、更小的构建和运行时 - 因为它可以动态加载主机操作系统的本机库(例如glibc,DNS 解析器等)。这是当地快速发展的理想选择。对于部署,CGO_ENABLED=1可能不切实际甚至不可能 - 在考虑部署托管操作系统时。

如果您纯粹使用标准库,则它们可能不一定需要启用 CGO。在某些标准库中,如果使用纯 Go 版本 ( CGO_ENABLED=1) 或启用 CGO 的版本,行为会有所不同:

  • net : 请参阅 DNS名称解析
  • 操作系统/用户
    • CGO_ENABLED=1使用本机操作系统(例如在 Linux 上nsswitch)进行 ID 查找
    • CGO_ENABLED=0使用基本的 Go 实现(例如从 读取/etc/passwd)-不包括主机可能知道的其他 ID 注册表

部署

虽然CGO_ENABLED=1二进制文件的大小可能较小,但它也依赖于提供主机操作系统。比较 Docker 镜像:

  • ubuntu:20.04是 73.9MB(glibc:GNU-libc)
  • alpine:3.12.1是 5.57MB ( musllibc)

所以添加一个操作系统(即使是最小的)会增加这个额外的负担。alpine它的最小尺寸看起来很有吸引力 - 但它libc可能与依赖glibc.

CGO_ENABLED=0然而,非常适合临时docker 镜像部署——因为不需要捆绑主机操作系统。

但是,如果您的应用程序导入带有 C 代码的包(例如go-sqlite3),那么您的构建必须启用 CGO。

  • 并且 `CGO_ENABLED=1` 不会使您的二进制文件变小,事实上它通常会使其稍微变大,因为它必须编译额外的代码来处理 cgo 以及 cgo 代码正在执行的其他操作。 (3认同)
  • 这里有多个合并的部分,它们都与“更快、更小的构建和运行时”无关。主机 libc 的默认用途是用于无法在 std lib 中复制的功能。`CGO_ENABLED=1` 是默认值,因为它是——它不需要是,但我们决定这将是最有用的默认值。它不会加速_任何事情_。在 C 库中链接速度较慢,因为您需要做更多工作来构建它。调用C库比较慢,因为切换堆栈需要一些时间。它与本地开发与部署无关,您需要哪个就使用哪个。 (2认同)