df63692a18
Deploy Examination / deploy (push) Successful in 31s
Cover 9 subtopics from the computer networking documentation: - http-handshake: TCP/TLS/HTTP2/HTTP3 handshakes - http-connection-cost: connection resource overhead & million concurrency - connection-pooling: pool reuse, HTTP/1.1 vs HTTP/2 - http-keepalive: Keep-Alive principle, head-of-line blocking - keepalive-scenarios: when to enable/disable Keep-Alive - domain-sharding: HTTP/1.1 hack, HTTP/2 obsolescence - cdn: edge nodes, caching, DDoS protection - cors: same-origin policy, preflight requests - go-build-strip: -s -w flags, binary size optimization
200 lines
8.5 KiB
JSON
200 lines
8.5 KiB
JSON
{
|
||
"topic": "go-build-strip",
|
||
"type": "fill_blank",
|
||
"schema_version": "1.0.0",
|
||
"generated": "2026-09-02T21:20:00+08:00",
|
||
"questions": [
|
||
{
|
||
"id": "fb-001",
|
||
"type": "fill_blank",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"Go",
|
||
"编译",
|
||
"符号表"
|
||
],
|
||
"question": "使用 go build -____ 命令可以剥离 Go 二进制文件中的符号表(symbol table),从而减小文件体积。",
|
||
"answer": [
|
||
"s",
|
||
"-s"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "-s 标志告诉 Go 链接器在生成二进制文件时不写入符号表。符号表包含了所有函数名、变量名、类型名等调试信息,生产环境中通常不需要。去掉符号表后,go tool nm 等工具将无法列出符号,二进制体积也会减小。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-002",
|
||
"type": "fill_blank",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"Go",
|
||
"编译",
|
||
"DWARF",
|
||
"调试信息"
|
||
],
|
||
"question": "使用 go build -____ 命令可以剥离 DWARF 调试信息,进一步减小 Go 二进制文件体积。",
|
||
"answer": [
|
||
"w",
|
||
"-w"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "-w 标志会去掉 DWARF(Debugging With Attributed Record Formats)调试信息。DWARF 是一种标准化的调试数据格式,包含了源码行号、局部变量、类型信息等。去掉 DWARF 后,dlv(Delve)等调试器将无法正常工作,go tool addr2line 也无法将地址翻译为行号。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-003",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"Go",
|
||
"编译",
|
||
"体积优化"
|
||
],
|
||
"question": "生产环境构建 Go 二进制时,推荐使用 go build -s -____ 组合标志,同时剥离符号表和 DWARF 调试信息以实现体积最小化。",
|
||
"answer": [
|
||
"w"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "-s 和 -w 组合使用可以最大程度地减小二进制体积。-s 去掉符号表,-w 去掉 DWARF 调试信息,两者独立且互补。通常可将二进制体积减少约 20%-30%。Go 编译器支持这两个标志独立或组合使用。注意:这个组合一旦应用,后续反查行号信息将不可用。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-004",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"Go",
|
||
"编译",
|
||
"体积优化"
|
||
],
|
||
"question": "使用 -s -w 编译标志对 Go 二进制进行体积优化,通常可以将文件大小减少约____。",
|
||
"answer": [
|
||
"20-30%",
|
||
"20%到30%",
|
||
"20%-30%"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "根据实际测试,-s -w 组合通常能使 Go 二进制体积减少 20%-30%。具体比例取决于原始二进制中符号表和调试信息的占比。一般来说,包含大量函数和类型的大型项目减小效果更明显。例如一个原本 20MB 的 Go 二进制,去掉后可能只有 14-16MB。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-005",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"Go",
|
||
"panic",
|
||
"堆栈信息"
|
||
],
|
||
"question": "使用 -s -w 编译的 Go 程序在发生 panic 时,堆栈跟踪信息中只能显示____名,而无法显示完整的源码路径。",
|
||
"answer": [
|
||
"文件",
|
||
"file",
|
||
"文件名"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "因为 -w 去掉了 DWARF 调试信息,panic 的堆栈跟踪虽然仍能显示函数名和文件名(这些信息被嵌入在 Go 运行时的 pclntab 中,与 DWARF 无关),但无法显示完整的源码绝对路径。函数名因为已编入 pclntab(Program Counter Line Table)所以仍然可用,但行号和路径信息不完整。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-006",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"Go",
|
||
"pprof",
|
||
"性能分析"
|
||
],
|
||
"question": "对使用 -s -w 编译的 Go 二进制文件运行 pprof 进行性能分析时,函数调用栈中只会显示内存____,而无法显示具体的函数名和行号信息。",
|
||
"answer": [
|
||
"地址",
|
||
"address"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "pprof 在分析 profiling 数据时需要符号信息来将内存地址翻译为函数名+行号。如果二进制用了 -s 去掉符号表,pprof 就无法解析这些地址,只能显示原始的十六进制地址。即使只用了 -w 去 DWARF,pprof 仍能显示函数名(符号表还在),只是没有行号。要让 pprof 正常工作,最好保存未 strip 的调试版本。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-007",
|
||
"type": "fill_blank",
|
||
"difficulty": 3,
|
||
"tags": [
|
||
"Go",
|
||
"ldflags",
|
||
"编译时注入"
|
||
],
|
||
"question": "使用 go build -ldflags \"-X ____.version=1.0.0\" 可以在编译时注入版本号等变量,这与 -s -w 组合使用互不影响。",
|
||
"answer": [
|
||
"main",
|
||
"包路径"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "-ldflags \"-X importpath.name=value\" 用于在编译时设置 string 类型的包级变量值。完整路径格式为 \"fully/qualified/package.Path\"。例如 main 包中的 version 变量:-ldflags \"-X main.version=1.0.0\"。这个操作通过链接器完成,与 -s -w 的符号剥离独立——因为 -X 是在编译时直接将值写入二进制数据段,不需要运行时符号表参与。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-008",
|
||
"type": "fill_blank",
|
||
"difficulty": 2,
|
||
"tags": [
|
||
"Go",
|
||
"开发环境",
|
||
"调试"
|
||
],
|
||
"question": "在本地开发和调试阶段,构建 Go 程序时____使用 -s -w 标志,以保留完整的调试信息便于使用 Delve 调试器和 pprof 工具。",
|
||
"answer": [
|
||
"不应该",
|
||
"不建议",
|
||
"不要"
|
||
],
|
||
"answer_rule": "any",
|
||
"explanation": "本地开发阶段保留调试信息至关重要。Delve(dlv)调试器依赖 DWARF 信息来设置断点、查看变量值、单步调试;pprof 依赖符号表来解析函数名和行号。如果开发时用了 -s -w,调试体验会严重下降。最佳实践:开发/测试环境不 strip,仅在 CI/CD 的生产构建中使用 -s -w。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-009",
|
||
"type": "fill_blank",
|
||
"difficulty": 4,
|
||
"tags": [
|
||
"Go",
|
||
"addr2line",
|
||
"调试"
|
||
],
|
||
"question": "当使用 -s -w 编译的程序 panic 输出中包含十六进制地址时,可使用 go tool ____ 反查对应的源码文件和行号,前提是能找到对应的未 strip 二进制。",
|
||
"answer": [
|
||
"addr2line"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "go tool addr2line 接收二进制文件和地址列表,输出对应的源码文件和行号。但它需要未 strip 的二进制(包含 DWARF 信息)作为输入。因此生产中如果要保留事后调试能力,需要在构建时同时保存 strip 和未 strip 两个版本。未 strip 版本用于事后分析,strip 版本用于部署。",
|
||
"source": null,
|
||
"related": []
|
||
},
|
||
{
|
||
"id": "fb-010",
|
||
"type": "fill_blank",
|
||
"difficulty": 5,
|
||
"tags": [
|
||
"Go",
|
||
"Rust",
|
||
"Java",
|
||
"跨语言对比"
|
||
],
|
||
"question": "在 Rust 中通过 Cargo.toml 的 [profile.release] 设置 strip = true 可实现类似 Go 的 -s 效果;在 Java 中,____/R8 等工具通过代码缩减和混淆实现类似的二进制体积优化。",
|
||
"answer": [
|
||
"ProGuard"
|
||
],
|
||
"answer_rule": "all",
|
||
"explanation": "不同语言都有二进制体积优化手段:Go 用 -s -w 剥离符号和调试信息;Rust 在 Cargo.toml 中设置 strip = true 或使用 strip 命令,效果类似;Java 使用 ProGuard(开源)或 R8(Android 官方,Google 开发的 ProGuard 替代品)进行 tree-shaking(移除未使用的类和方法)、混淆和优化。虽然原理不同(Go/Rust 是剥离元数据,Java 是缩减代码),但目标一致——减小部署体积。其他语言也有类似工具:C/C++ 的 strip 命令、.NET 的 PublishTrimmed 等。",
|
||
"source": null,
|
||
"related": []
|
||
}
|
||
]
|
||
} |