go的十万个为什么?-执行程序|Go主题月

726 阅读6分钟

本文中译于官方FAQ

原文地址:golang.org/doc/faq#Fun…

Go 项目执行程序

编译器使用什么编译器技术?

有几种针对Go的产品编译器,还有许多针对各种平台的开发中的编译器。

默认的编译器gc包含在 Go 发行版中,作为对 go 命令的支持的一部分。Gc最初是用 C 语言编写的,原因是引导过程很困难,您需要 Go 编译器来设置 Go 环境。自Go 1.5发行以来,编译器一直是Go程序。如本设计文档talk中所述,使用自动翻译工具将编译器从C转换为Go 。因此,编译器现在是“自托管”的,这意味着我们需要面对引导问题。解决方案是已经有一个可以正常运行的Go安装,就像正常情况下可以正常工作的C安装一样。如何打开来自源的新进入环境中的故事描述在这里这里

Gc是用 Go 编写的,具有递归下降解析器,并使用一个也是基于Go编写但基于Plan 9加载程序的自定义加载程序来生成ELF / Mach-O / PE二进制文件。

在项目开始时,我们考虑将 LLVM 用于gc,但认为它太大且太慢,无法满足我们的性能目标。回想起来,更重要的是,从 LLVM 开始将使引入 Go 所需但不属于标准 C 设置的 ABI 和相关更改(例如堆栈管理)变得更加困难。但是,新的LLVM实施 现在开始出现。

Gccgo编译器是用C++编写的前端,具有递归下降解析器,该解析器与标准GCC后端耦合。

事实证明,使用 Go 语言是实现 Go 编译器的一种很好的语言,尽管这并不是其最初的目标。从一开始就没有自我托管功能,这使Go的设计可以专注于其最初的用例,即网络服务器。如果我们决定 Go 应该尽早进行编译,那么我们可能最终会开发出一种更多针对于编译器构建的语言,这是一个值得的目标,但并不是我们最初的目标。

尽管gc尚未使用它们(还可以吗?),但是go程序包中提供了本机词法分析器和解析器,并且还有一个本机类型检查器

运行时支持如何实现?

再次由于引导问题,运行时代码最初主要是用C编写的(只有少量汇编程序),但此后已转换为Go(某些汇编程序位除外)。Gccgo的运行时支持使用glibcgccgo编译器使用一种称为分段堆栈的技术来实现 goroutine,该程序得到了对 gold 链接器的最新修改的支持。 Gollvm 类似地建立在相应的 LLVM 基础架构上。

为什么我的程序二进制文件这么大?

默认情况下,gc工具链中的链接器创建静态链接的二进制文件。因此,所有Go二进制文件都包含 Go 运行时,以及支持动态类型检查,反射甚至紧急时间堆栈跟踪所必需的运行时类型信息。

在 Linux 上使用gcc静态编译并静态链接的一个简单的C hello,world程序约为750 kB,其中包括printf的实现。使用fmt.Printf的等效Go程序重达几兆字节,但其中包括更强大的运行时支持以及类型和调试信息。

可以将使用gc编译的 Go 程序与-ldflags = -w标志链接以禁用 DWARF 生成,从而从二进制文件中删除调试信息,但不会造成其他功能损失。这样可以大大减小二进制大小。

我可以取消对未使用的变量或导入的包的爆红吗?

未使用的变量的存在可能表示错误,而未使用的导入只会减慢编译速度,随着程序随着时间的推移积累代码和程序员,这种影响可能会变得很明显。由于这些原因,Go 拒绝使用未使用的变量或导入来编译程序,为了短期的构建速度和程序的清晰性而使用短期的便利性。

但是,在开发代码时,通常会临时创建这些情况,并且在程序编译之前必须将它们进行编辑可能会很烦人。

有些人要求使用编译器选项来关闭这些检查或至少将其减少为警告。不过,由于编译器选项不应影响语言的语义,并且因为Go编译器不报告警告,因此仅添加阻止编译的错误,因此未添加此类选项。

没有警告有两个原因。首先,如果值得抱怨,则值得在代码中进行修复(如果不值得修复,则不值得一提)。其次,让编译器生成警告会鼓励实现对可能会使编译嘈杂的弱情况发出警告,从而掩盖了应修复的实际错误。

不过,解决这种情况很容易。使用空白标识符可以在开发过程中保留未使用的东西。

import "unused"

// This declaration marks the import as used by referencing an
// item from the package.
var _ = unused.Item  // TODO: Delete before committing!

func main() {
    debugData := debug.Profile()
    _ = debugData // Used only during debugging.
    ....
}

如今,大多数 Go 程序员都使用goimports工具,它会自动重写 Go 源文件以具有正确的导入,从而消除了实践中未使用的导入问题。编写 Go 源文件时,该程序可轻松连接到大多数编辑器,以自动运行。

为什么我的病毒扫描软件认为我的Go发行版或编译的二进制文件已被感染?

这是常见的现象,尤其是在 Windows 计算机上,并且几乎总是假阳性。

商业病毒扫描程序经常被 Go 二进制文件的结构所迷惑,它们看起来不像使用其他语言编译的二进制文件那样频繁。

如果您刚刚安装了Go发行版,并且系统报告它已被感染,那肯定是一个错误。确实,您可以通过将校验和与下载页面上的校验和进行比较来验证下载。

无论如何,如果您认为报告有误,请向病毒扫描程序的供应商报告错误。也许病毒扫描程序可以及时了解 Go 程序。