☰
90DaysOfDevOps 第 9 天:逐行拆解 Go 的 Hello World 代码——从编译原理到 package、import 与 main 函数
2026/10/7 2:36:56 网站建设 项目流程
  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载

导读

本文是《90DaysOfDevOps》学习路线中 Go 语言模块的第 9 天(对应 2022/pt-br/Days/day09.md),在 第 8 天 完成 Go 安装并写出第一个main.go之后,这里将把那份只有 6 行的 Hello World 程序逐行拆解,讲清楚"编译"到底做了什么、"包(package)"为什么存在、package main与func main()为什么是强制规则、import "fmt"与fmt.Println()又如何协作。读完本文,你将能够独立解释 Go 程序的启动流程,并具备阅读与扩展 2022/Days/Go/hello.go 这类入门源码的基础能力。

图为第 8 天创建main.go后使用go build main.go将人类可读的源代码编译为机器可执行程序的过程示意。

为什么需要先理解"编译"

在逐行读代码之前,必须先建立对编译的基本认知。Python、Java、Go、C++ 等我们常用的编程语言都属于高级语言(high-level languages):它们以人类可读的文本形式存在。但机器(CPU)真正执行程序时,需要的是机器码(machine code)。因此我们必须把人类可读的源代码"翻译"成机器能理解的形式,这个过程就叫编译(compiling)。

回到 第 8 天 的操作:我们创建了一个简单的main.go,然后执行

go build main.go

这条命令就会把源代码编译成可执行的二进制文件。第 8 天还演示了另一种运行方式:

go run main.go

两者的区别值得说明:go run会先编译再立即运行,适合开发调试阶段快速验证;go build只产出可执行文件,适合最终分发。第 8 天文档中还展示了构建产物(Windows 下为main.exe)执行后输出Hello #90DaysOfDevOps的过程。

一个非常实用的补充是:Go 支持交叉编译(cross-compilation),即在一次构建中为多个操作系统与 CPU 架构产出二进制。仓库中的 2022/Days/Go/makefile 就给出了一个真实示例:

BINARY_NAME=90DaysOfDevOps build: GOARCH=amd64 GOOS=darwin go build -o ${BINARY_NAME}_0.2_darwin main.go GOARCH=amd64 GOOS=linux go build -o ${BINARY_NAME}_0.2_linux main.go GOARCH=amd64 GOOS=windows go build -o ${BINARY_NAME}_0.2_windows main.go GOARCH=arm64 GOOS=linux go build -o ${BINARY_NAME}_0.2_linux_arm64 main.go GOARCH=arm64 GOOS=darwin go build -o ${BINARY_NAME}_0.2_darwin_arm64 main.go

可以看到,通过设置GOOS(目标操作系统)与GOARCH(目标 CPU 架构)两个环境变量,同一份main.go可以同时产出 macOS、Linux、Windows 以及 arm64 架构的可执行文件——这正是"编译"环节在工程实践中的价值体现。

什么是包(Package)

包(package)是 Go 组织源码的基本单位:它是同一个目录下、被编译在一起的一组源文件。更直白地说,包就是同一目录下的一堆.go文件。

沿用第 8 天创建的Hello文件夹:当你进入更复杂的 Go 程序后,可能会发现程序由folder1、folder2、folder3等多个目录构成,每个目录各自包含不同的.go文件,组合起来就是一个由多个包组成的完整程序。

使用包带来的核心收益是代码复用:我们不必从零手写一切。比如程序里需要计算器功能,很可能已经存在包含数学函数的现成 Go 包,直接导入到代码中即可,长期来看能节省大量时间与精力。Go 官方鼓励将代码组织成包,正是为了让源码更容易复用、更容易维护。

打开我们的 Hello World:逐行拆解

下面是 2022/Days/Go/hello.go 的完整内容(仓库中实际保存的版本,输出消息为"Until tomorrow #90DaysOfDevOps",与第 8 天首次创建的"Hello #90DaysOfDevOps"略有不同,属正常迭代):

package main import "fmt" func main() { fmt.Println("Until tomorrow #90DaysOfDevOps") }

图为main.go源码文件在编辑器中打开后的整体视图,本文接下来按行逐一讲解。

第 1 行:package main

第一行写着package main,表示这个文件归属于名为main的包。所有.go文件都必须归属某个包,并且第一行必须是package 包名形式的声明。

包的名称可以按你的意愿命名,但这里的main是一个规则约定:因为程序执行的起点就在这个包里,所以包含入口的程序包必须命名为main。这一点可以从仓库中的多个示例得到印证——2022/Days/Go/day11_example1.go、day12_example1.go等后续天数的示例文件,第一行同样都是package main。

第 5 行:func main()——程序的入口

无论何时编译并执行代码,我们都必须告诉机器"执行从哪里开始"。Go 通过一个名为main的函数来完成这件事:机器会在程序包中查找名为main的函数,把它当作程序入口点。

函数(function)是一段能够完成特定任务、并可在整个程序中被调用的代码块。用关键字func可以声明任意名字的函数,但在这个场景下必须命名为main,因为它是代码开始执行的地方。

注意第 2 行是空行,第 4 行的func main() {后面是函数体开始。仓库中的 2022/Days/Go/hello.go 第 5~7 行即为此函数体:

func main() { fmt.Println("Until tomorrow #90DaysOfDevOps") }

第 3 行:import "fmt"

第 3 行的import表示你要把另一个包引入到你的主程序中。这里导入的是 Go 官方提供的标准包fmt,该包内包含Println()函数——正是由于这一行 import,我们才能够在第 6 行使用它。

Go 自带大量标准库包(涵盖格式化、I/O、字符串、网络等领域),你可以把它们引入自己的程序并复用,省去从零编写底层功能的麻烦。第 8 天安装 Go 后,编辑器中提示安装的扩展与依赖包,正是为了支持这类标准包的使用。

第 6 行:fmt.Println()

这里的fmt.Println()是向**标准输出(stdout)**写入文本的方式:无论可执行文件在哪里被成功运行,终端上都会显示括号内的消息。你完全可以自由修改()之间的内容,例如改成你自己的挑战标语。

从 2022/Days/Go/day11_example1.go 可以看到fmt.Println的更多用法——它可以同时接收多个参数:

package main import "fmt" func main() { var challenge = "#90DaysOfDevOps" fmt.Println("Welcome to", challenge, "") }

这印证了fmt.Println是可变参数函数,可以一次性打印字符串与变量的组合,这也是它在 Go 入门教学中被高频使用的原因。

快速回顾(TLDR)

对照上面的逐行讲解,把 6 行代码的职责浓缩为一张速查清单:

  • 第 1 行= 这个文件属于名为main的包;必须叫main,因为它包含程序的入口点。
  • 第 3 行= 为了使用Println(),必须导入fmt包,这样它才能在第 6 行被调用。
  • 第 5 行= 真正的起点,即main函数。
  • 第 6 行= 在系统上打印出Hello #90DaysOfDevOps(或仓库中的"Until tomorrow #90DaysOfDevOps")。

这张清单可以作为你后续阅读任何 Go 程序的"起手式":先定位package main,再找func main(),再看 import 了哪些标准包、入口函数里调用了哪些函数。

下一步

掌握了编译、包与入口函数的机制之后,第 10 天将继续沿着 Go 语言的学习路径深入(参见 2022/Days/day10.md)。本仓库2022/Days/Go/目录下保存了后续多天(第 11~13 天)的示例源码,例如day11_example1.go~day13_example3.go,均可作为动手阅读与修改的练习材料;对应的逐日讲解见 2022/Days/day11.md、2022/Days/day12.md 与 2022/Days/day13.md。

  • 文档/教程

【免费下载链接】90DaysOfDevOps

This repository started out as a learning in public project for myself and has now become a structured learning map for many in the community. We have 3 years under our belt covering all things DevOps, including Principles, Processes, Tooling and Use Cases surrounding this vast topic.

项目地址:https://gitcode.com/gh_mirrors/90/90DaysOfDevOps
点击查看免费下载
上一篇:如何快速把SketchUp模型转成3D打印STL文件:sketchup-stl插件完整上手指南
下一篇:SketchUp与STL格式转换太难?免费开源插件sketchup-stl,5分钟从安装到打印全攻略

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询