快速掌握 Go 二进制文件的静态和动态链接

大家好,我是煎鱼。

在编写 Go 应用程序时,Go 本身提供了跨平台编译,提供了非常大的便利。但内部其实有许多静态和动态链接的相关知识点。

今天给大家分享这一块的基本知识。

如何选择?Go 团队的讨论

Go 核心团队在创造这门编程语言时已经做了大量的讨论和权衡。

769766f46808b395c3c8637a08db0286.png

“静态链接有很多优点。部署简单是其中之一。没有版本问题是另一个优点(升级可能永远不会破坏您的 go 二进制文件。但动态链接或解释语言则不然,因为依赖关系可能会中断)。启动时间更快也是另一个优点。

不过,动态链接也有很好的理由。真实原因是:因为 go 作者已经研究了静态链接与动态链接的权衡,并决定静态链接更适合他们的用例。而且 go 社区中的大多数人都同意这一点。”

静态和动态链接是什么?

静态和动态链接是两种不同的程序链接方式,一般会根据实际的程序运行情况进行选择。

9695cfdcaab5af9583f57222198af5b2.png
图片来自网络

静态链接

在编译时,链接器将程序所需的所有库文件直接复制到可执行文件中,生成一个完整的可执行文件。

一旦生成后,执行时不再依赖外部库。

  • 优点:简单且不需要额外的库文件。

  • 缺点:可执行文件较大,更新库时需要重新编译。

动态链接

在程序运行时,操作系统根据需要加载共享库到内存中。

这使得可执行文件更小,因为它不包含所有的库代码,但程序执行时依赖于外部库的存在。

  • 优点:在于节省内存和便于库的更新。

  • 缺点:可能存在一些版本兼容性问题等。

快速例子

静态链接

对于 Go 这一门编程语言而言,静态链接是他大力宣传的一个招牌:只需要编译一个二进制文件,哪里都可以部署。

示例代码如下:

package main

import (
 "fmt"
)

func main() {
 fmt.Println("脑子进煎鱼了!")
}

输出结果:

脑子进煎鱼了!

强制指定 CGO_ENABLED=0 来进行编译:

CGO_ENABLED=0 go build main.go

使用 file 工具查看目标文件信息:

$ file greet
greet: Mach-O 64-bit executable arm64

结合查看 fmt.Println 是否固定地址:

a53476fdd6e6a2ded427274112e6f5ca.png

结合来看,可以确定 Go 程序本身的依赖是静态链接的。而编译出来的二进制程序到底有没有动态链接库,取决于你所编写的程序。

动态链接

Go 应用程序在进行 go build 的时候,可以加入 -buildmode 参数来指定构建模式,以此实现动态链接的目的。

以下是可用的 buildmode 选项:

  • archive: 将非 main 包构建成 .a 文件,main 包将被排除。

  • c-archive: 构建 main 包及其依赖的所有包为 C 归档文件。

  • c-shared: 构建指定的 main 包及其所有依赖为 C 动态库。

  • shared: 将所有非 main 包整合到一个动态库中。

  • exe: 构建指定的 main 包及其依赖为可执行文件,未命名为 main 的包将被忽略。

默认情况下,main 包会被内置到可执行文件中,非 main 包则会被内置到 .a 文件中。

这块我们写 Web 程序的用的不多,如果是写 C 库或者调第三方语言的动态库时用得多。此时需要在编译时指定 CGO_ENABLED=1 才可以。

有兴趣的话,CGO 例子可以参考:andreiavrammsd/cgo-examples[1],这里不展开。

总结

今天我们快速的介绍了 Go 语言中的静态和动态链接的基本概念,打了个底。静态链接会实现 ALL IN ONE 的效果,确保编译出来的二进制文件能够在标准的环境下运行。而动态链接则相反。

这是 Go 这门编程语言设计时的一个招牌特性,而我们做 Web 开发的话,一般都是以静态链接为主。

如果有涉及到第三方调用才会用到动态链接等。我见过用 CGO 逐步重构 C 服务的,甚至要慎防内存泄露。这时候又是另外一套逻辑、体系了,要进一步进修!

推荐阅读

参考资料

[1]

andreiavrammsd/cgo-examples: https://github.com/andreiavrammsd/cgo-examples

关注和加煎鱼微信,

一手消息和知识,拉你进技术交流群👇

80be7c68bf4698e765cf9bdb922340b1.jpeg

cc94510c5d0e50ac9199ef6d74cb036b.png

你好,我是煎鱼,出版过 Go 畅销书《Go 语言编程之旅》,再到获得 GOP(Go 领域最有观点专家)荣誉,点击蓝字查看我的出书之路

日常分享高质量文章,输出 Go 面试、工作经验、架构设计,加微信拉读者交流群,和大家交流!

原创不易 点赞支持

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值