练习
学完本章你应该掌握
- 能把一个真正可运行的
main包用go build编译成可执行文件,并根据场景使用-o指定清晰的产物名。 - 能根据目标系统和架构写出正确的
GOOS、GOARCH组合,产出 Windows、Linux、macOS 等不同平台版本。 - 能识别哪些项目当前不能直接打包,例如目录不是
main包、没有入口函数、打包前测试没过等问题。 - 能在部署时区分“二进制文件”和“运行时依赖”,知道配置文件、数据文件、模板和静态资源不会自动跟着普通打包一起进入二进制。
- 能把前面学过的函数、切片、map、文件操作、测试、HTTP、TCP、错误处理等知识自然放进部署场景,而不是只会机械背命令。
简单
第 1 题:打包一个成绩摘要工具
编写一个 Go 程序,完成下面要求:
- 编写函数
calcAvg(scores []int) float64 - 在
main中准备切片:
| |
- 输出:
| |
- 再把当前程序打包成一个名为
score-tool的可执行文件
查看参考答案
| |
打包命令:
| |
说明:
- 这道题真正要练的是:先有一个能运行的
main包,再执行go build -o ...生成可执行文件。 - 如果你当前在 Windows 上练习,也可以把输出名写成
score-tool.exe,这样更直观。
第 2 题:修正无法生成可执行文件的程序入口
下面这段代码的目标是统计成绩总分和平均分,但它当前不能直接打包成可执行文件。请改正后让它可以正常打包,并输出:
| |
| |
额外要求:
- 让当前目录成为一个可执行程序
- 写出 Windows 下的打包命令,输出文件名为
report.exe
查看参考答案
修正后的代码如下:
| |
打包命令:
| |
关键点:
- 只有
main包并且存在main()入口函数时,当前目录才适合直接打包成可执行文件。 - 原代码更像一个普通库包,能被别人调用,但不能直接当程序入口运行。
第 3 题:为同一个程序生成 Windows 和 Linux 版本
假设你当前目录已经有一个可正常打包的 main 程序。请使用 PowerShell 写出下面两条打包命令:
- 生成
windows/amd64可执行文件summary.exe - 生成
linux/amd64可执行文件summary-linux
查看参考答案
| |
说明:
GOOS表示目标操作系统,GOARCH表示目标 CPU 架构。- Windows 目标文件通常带
.exe,Linux 目标文件一般不带。 - 在同一个终端里反复切换平台时,要记得每次都确认当前
GOOS和GOARCH,不要把上一次的目标平台误带到下一次构建里。
第 4 题:打包一个 HTTP 健康检查服务
编写一个 Go 程序,完成下面要求:
- 使用
net/http启动一个 HTTP 服务 - 注册路由
/health - 访问
/health时返回:
| |
- 服务监听
:8080 - 再把当前程序打包成名为
health-server的可执行文件
查看参考答案
| |
打包命令:
| |
说明:这道题虽然顺手复习了上一单元的 HTTP 服务端,但主考点仍然是“先有一个可运行服务,再把它编译成部署产物”。
第 5 题:交叉编译一个 TCP 客户端
编写一个 Go 程序,完成下面要求:
- 使用
net.Dial连接127.0.0.1:9000 - 向服务端发送
ping - 读取服务端响应并输出
- 最后把这个程序交叉编译成
linux/amd64版本 - 输出文件名为
tcp-client-linux
查看参考答案
| |
PowerShell 交叉编译命令:
| |
说明:
- 这道题让你在打包时顺手复习
TCP客户端的最小读写流程。 - 真正运行客户端前,仍然需要先准备好对应的服务端;但“能不能运行”和“能不能编译出目标平台的产物”是两个不同层面的检查。
一般
第 6 题:先测试再打包成绩等级工具
编写一个 Go 小工具,完成下面要求:
- 在
grade.go中编写函数Grade(score int) string - 规则如下:
| |
- 在
main中输出:
| |
- 再在
grade_test.go中使用表格驱动子测试,至少覆盖下面 4 个场景:59 -> D60 -> C90 -> A101 -> 非法 - 最后先运行测试,再打包成
grade-tool
查看参考答案
grade.go
| |
grade_test.go
| |
建议命令:
| |
说明:
- 这道题的部署主线是“打包前先做基本验证”,不是测试章节的重复。
- 读者在这一步会自然复习函数、
switch、子测试和go test,但最终目标仍然是得到一个更可靠的可执行文件。
第 7 题:部署一个依赖配置文件的程序
编写一个 Go 程序,完成下面要求:
- 编写函数
loadMode(path string) (string, error) - 从
app.conf中读取一行配置:
| |
- 在
main中输出:
| |
- 把程序打包成
mode-reader - 最后回答:部署到目标机器时,除了二进制文件,还需要一起带上什么文件
查看参考答案
| |
打包命令:
| |
部署时还需要一起带上的文件:
| |
说明:
- 运行这个程序前,要先确保当前目录里已经准备好了
app.conf,内容例如mode=dev。 - 普通
go build只会生成二进制文件,不会自动把运行时要读取的配置文件一起打进去。 - 这正是部署章节里非常容易忽略的一点:程序能编译成功,不等于目标机器上运行时一定能找到依赖文件。
第 8 题:一次产出三个平台版本
假设你当前目录里已经有上一题的 mode-reader 程序,并且你准备在打包前先跑测试。请使用 PowerShell 写出下面这组命令:
- 先运行所有测试
- 再生成
windows/amd64版本:mode-reader.exe - 再生成
linux/amd64版本:mode-reader-linux-amd64 - 再生成
darwin/arm64版本:mode-reader-darwin-arm64
查看参考答案
| |
说明:
- 三个平台的核心差别就在
GOOS、GOARCH和产物命名上。 - Windows 版本带
.exe,Linux 和 macOS 版本一般不带。 - 如果你后面还要继续打本机版本,记得重新检查当前终端里的目标平台变量,不要把前面的交叉编译设置误带到后续构建中。
进阶
第 9 题:部署一个成绩查询 HTTP 服务
请完成一个稍微完整一点的小场景:
- 编写函数
loadScores(path string) (map[string]int, error) - 从
scores.txt中按行读取学生成绩,文件内容格式如下:
| |
- 程序启动时先加载这份成绩表
- 启动一个 HTTP 服务,监听
:8080 - 注册路由
/score - 访问方式示例:
| |
- 如果找到了,返回:
| |
- 如果没找到,返回:
| |
- 最后写出:
- 本机打包命令,输出
score-server linux/amd64交叉编译命令,输出score-server-linux- 部署到 Linux 机器时需要一起上传的文件
- 本机打包命令,输出
查看参考答案
| |
本机打包命令:
| |
PowerShell 交叉编译 Linux:
| |
部署到 Linux 机器时需要一起上传的文件:
| |
说明:
r.URL.Query().Get("name")用来读取查询参数,这是在 HTTP 服务里很常见的取参方式。- 这道题把文件读取、
map查询、错误处理和 HTTP 服务端串起来了,但整道题的核心仍然是:把真实服务程序编译成部署产物,并且别忘了它运行时依赖的数据文件。
第 10 题:在同一仓库里分别打包 server 和 client
请完成一个稍微扩展一点的部署练习:
- 在同一个仓库中准备两个可执行程序:
server/main.goclient/main.go
server/main.go的要求: 启动 HTTP 服务 注册/hello访问时返回:
| |
client/main.go的要求: 请求http://127.0.0.1:8080/hello读取响应体并输出最后写出下面三条打包命令:
- 打包服务端,输出
hello-server - 打包客户端,输出
hello-client - 交叉编译
linux/amd64的服务端版本,输出hello-server-linux
- 打包服务端,输出
提示:这题比正文多走了一步。正文主要演示的是“打包当前目录”,这里额外练的是“在一个仓库里打包不同子目录下的 main 包”。
查看参考答案
server/main.go
| |
client/main.go
| |
打包命令:
| |
PowerShell 交叉编译 Linux 服务端:
| |
说明:
./server和./client表示要构建的是哪个子目录下的包,而不是当前根目录。- 当一个仓库里同时存在多个
main程序时,这种按包路径打包的写法很常见,也很接近真实项目里的发布流程。