提到跨平台开发,就首先想到C语言,准确的说应该叫ANSI C。
ANSI C是由美国国家标准协会(ANSI)及国际标准化组织(ISO)推出的关于C语言的标准。ANSI C 主要标准化了现存的实现, 同时增加了一些来自 C++ 的内容 (主要是函数原型) 并支持多国字符集 (包括备受争议的三字符序列)。ANSI C 标准同时规定了 C 运行期库例程的标准。一些开源项目根据ANSI C标准进行开发后,可移植行就非常好。
但无奈,随着新指令集的CPU不断出现,如果开发者自己要从ANSI C方式去编码,实现减少由于不同软硬件架构的差异对上层应用的影响,那属实要做很大的基础工作。
所以当更加专业的语言Go出来后,由于设计者基于既往设计C语言的成功经验去粗取精,又结合近二三十年来的CPU架构和操作系统、云计算的新趋势,而造出了Go这样的多平台多CPU通吃的语言。正是这种定位,所以Go语言在可执行文件的链接方面就与众不同。
比如当小白不小心把linux系统的底层加载程序 ld-linux.so 文件删掉了,
准备跑路吧~~
因为此后系统内所有C/C++/Python/Nodejs/PHP/Java等语言开发编译的可执行文件,全都启动失败,出现莫名其妙的错误,比如cp命令是存在于/usr/bin/cp路径的文件,但此时调用cp,报错No such file or directry。
这是因为以上Python等所列的语言,本质上都是C语言开发的,它们的可执行文件的底层链接的系统动态库,要想运行都先依赖于 ld-linux.so 帮它们处理好ELF的二进制可执行文件、链接库的代码段落、数据段等内容加载到内存,然后CPU根据二进制指令执行代码逻辑,处理数据,完成计算任务。而这个底层的ld-linux.so动态库文件一旦自身不保,那么,其他依赖的软件当然全部异常。
而我们之前编译的Go的main函数测试二进制文件main。仍然能启动。
那么Go语言是如何独步江湖的呢?可以推断,Go的链接方式不使用ld-linux.so。
Go的编译器生成的静态链接的GO应用二进制文件,已包含了可供完整载入内存和需要的所有指令。既然这样,不管是Linux发行版A还是B系统自带的glibC 的版本是否过时,是否过新,跟GO能否正常运行关系不大。GO软件运行所需的都已经自给自足了。也因此Go可以带着它的干粮,不管丢到哪里就可以在那里运行。
当然,这离不开Go语言开发团队背后做了很多底层适配兼容,帮应用开发者省去了这份操心。也让这门语言兑现了它所吹过的牛。
下图为Golang 最新版1.21.5所支持的CPU架构、操作系统信息,实际Go目前能支持的已经超过这些平台范围。部分小众的系统架构也支持,图中未列出。