feat: add 180 questions (90 sc + 90 fb) for networking subtopics
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
This commit is contained in:
2026-09-02 21:33:09 +08:00
parent 0fbdefb626
commit df63692a18
28 changed files with 4143 additions and 1 deletions
@@ -0,0 +1,200 @@
{
"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": []
}
]
}
@@ -0,0 +1,42 @@
{
"slug": "go-build-strip",
"name": "Go Build Strip",
"description": "",
"tags": [
"DWARF",
"Go",
"Java",
"Rust",
"addr2line",
"ldflags",
"panic",
"pprof",
"体积优化",
"堆栈信息",
"开发环境",
"性能分析",
"符号表",
"编译",
"编译时注入",
"调试",
"调试信息",
"跨语言对比"
],
"difficulty_range": [
2,
5
],
"schema_version": "1.0.0",
"updated": "2026-09-02",
"question_files": [
"single_choice",
"fill_blank"
],
"stats": {
"total": 20,
"by_type": {
"single_choice": 10,
"fill_blank": 10
}
}
}
@@ -0,0 +1,218 @@
{
"topic": "go-build-strip",
"type": "single_choice",
"schema_version": "1.0.0",
"generated": "2026-09-02T21:20:00+08:00",
"questions": [
{
"id": "sc-001",
"type": "single_choice",
"difficulty": 2,
"tags": [
"Go",
"编译",
"-s"
],
"question": "Go 编译标志 -s 的作用是什么?",
"options": {
"A": "启用安全模式",
"B": "剥离符号表(函数名、变量名等调试符号)",
"C": "启用静态编译",
"D": "开启优化"
},
"answer": "B",
"explanation": "-s 标志剥离符号表(函数名、变量名等调试符号),-w 标志剥离 DWARF 调试信息。-s -w 组合体积最小化,最适合发布部署。",
"source": null,
"related": []
},
{
"id": "sc-002",
"type": "single_choice",
"difficulty": 3,
"tags": [
"Go",
"编译",
"-w"
],
"question": "Go 编译标志 -w 的作用是什么?",
"options": {
"A": "剥离符号表",
"B": "剥离 DWARF 调试信息(gdb/lldb 所需的详细信息)",
"C": "启用警告",
"D": "开启 Web 支持"
},
"answer": "B",
"explanation": "-w 标志剥离 DWARF 调试信息,这是 gdb/lldb 等调试器所需的详细信息。剥离后无法用 gdb 调试。",
"source": null,
"related": []
},
{
"id": "sc-003",
"type": "single_choice",
"difficulty": 3,
"tags": [
"Go",
"编译",
"体积"
],
"question": "使用 -s 标志编译后,二进制体积大约能减少多少?",
"options": {
"A": "5-10%",
"B": "20-30%",
"C": "50-60%",
"D": "70-80%"
},
"answer": "B",
"explanation": "使用 -s 标志剥离符号表后,二进制体积大约能减少 20-30%。实际节省取决于程序复杂度。",
"source": null,
"related": []
},
{
"id": "sc-004",
"type": "single_choice",
"difficulty": 4,
"tags": [
"Go",
"编译",
"panic"
],
"question": "使用 -s 标志后,panic 堆栈输出会有什么变化?",
"options": {
"A": "完全看不到函数名",
"B": "函数名还在,但完整源码路径丢失",
"C": "没有变化",
"D": "只显示地址"
},
"answer": "B",
"explanation": "使用 -s 剥离符号表后,函数名还在,但完整源码路径丢失。例如从 /home/user/app/main.go:42 变成 main.go:42。",
"source": null,
"related": []
},
{
"id": "sc-005",
"type": "single_choice",
"difficulty": 3,
"tags": [
"Go",
"编译",
"pprof"
],
"question": "剥离符号表后,go tool pprof 会显示什么?",
"options": {
"A": "完整的函数名",
"B": "只有地址(如 0x4a3b20)",
"C": "错误信息",
"D": "没有变化"
},
"answer": "B",
"explanation": "剥离符号表后 pprof 只显示地址(如 0x4a3b20),无法定位到具体函数。线上排查性能问题时非常痛苦。",
"source": null,
"related": []
},
{
"id": "sc-006",
"type": "single_choice",
"difficulty": 2,
"tags": [
"Go",
"编译",
"生产环境"
],
"question": "生产环境发布 Go 程序时应该使用什么编译标志?",
"options": {
"A": "不加任何标志",
"B": "-s -w",
"C": "只用 -w",
"D": "只用 -s"
},
"answer": "B",
"explanation": "生产环境发布应该使用 -s -w 组合,体积最小化,最适合发布部署。同时可以结合 -ldflags 注入版本号等构建信息。",
"source": null,
"related": []
},
{
"id": "sc-007",
"type": "single_choice",
"difficulty": 4,
"tags": [
"Go",
"编译",
"-ldflags"
],
"question": "go build -ldflags=\"-s -w -X main.Version=1.0\" 中 -X 的作用是什么?",
"options": {
"A": "设置编译器参数",
"B": "在剥离调试信息的同时注入编译时变量",
"C": "启用交叉编译",
"D": "设置输出文件名"
},
"answer": "B",
"explanation": "-X 用于在编译时注入变量值,可以同时剥离调试信息(-s -w)和注入版本号、构建时间等信息。",
"source": null,
"related": []
},
{
"id": "sc-008",
"type": "single_choice",
"difficulty": 3,
"tags": [
"Go",
"编译",
"调试"
],
"question": "以下哪种场景不应该使用 -s 标志?",
"options": {
"A": "生产环境部署",
"B": "CI/CD 构建产物",
"C": "本地开发调试",
"D": "嵌入式/IoT"
},
"answer": "C",
"explanation": "本地开发调试需要完整调试信息,不应该使用 -s 标志。生产环境部署、CI/CD 构建产物、嵌入式/IoT 都适合使用 -s -w。",
"source": null,
"related": []
},
{
"id": "sc-009",
"type": "single_choice",
"difficulty": 4,
"tags": [
"Go",
"编译",
"addr2line"
],
"question": "使用 -s -w 后线上出问题,如何通过地址反查行号?",
"options": {
"A": "go tool pprof",
"B": "go tool addr2line",
"C": "go tool trace",
"D": "go tool vet"
},
"answer": "B",
"explanation": "如果保留了构建时生成的 debug info 备份,可以用 go tool addr2line 通过地址反查行号。这是 -s -w 后排查问题的方法之一。",
"source": null,
"related": []
},
{
"id": "sc-010",
"type": "single_choice",
"difficulty": 2,
"tags": [
"Go",
"编译",
"语言对比"
],
"question": "以下哪种语言有类似 Go -s -w 的功能?",
"options": {
"A": "Python",
"B": "Rust(strip = true in Cargo.toml)",
"C": "JavaScript",
"D": "Shell"
},
"answer": "B",
"explanation": "Rust 在 Cargo.toml 中设置 strip = true 可以剥离调试信息,类似 Go 的 -s -w。C/C++ 有 strip 命令,Java 有 ProGuard/R8。",
"source": null,
"related": []
}
]
}