<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>工程化 on 鹿鸣青野的blog</title><link>https://www.sylgalaxy.xyz/tags/%E5%B7%A5%E7%A8%8B%E5%8C%96/</link><description>Recent content in 工程化 on 鹿鸣青野的blog</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Tue, 13 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://www.sylgalaxy.xyz/tags/%E5%B7%A5%E7%A8%8B%E5%8C%96/index.xml" rel="self" type="application/rss+xml"/><item><title>go mod 依赖管理</title><link>https://www.sylgalaxy.xyz/posts/go-04-01-go-mod/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-01-go-mod/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 CMake+Conan/vcpkg 到 Go modules：官方集成、语义化版本与可复现构建&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 自 1.11 起引入 &lt;strong&gt;Go modules&lt;/strong&gt;（常称 &lt;code&gt;go mod&lt;/code&gt;）作为官方依赖管理工具，1.16 起默认启用。它把「依赖管理」内置到工具链里，一个 &lt;code&gt;go.mod&lt;/code&gt; 文件声明模块与依赖，&lt;code&gt;go.sum&lt;/code&gt; 锁定依赖的校验和，配合**语义化版本（v1.2.3）**和 &lt;code&gt;GOPROXY&lt;/code&gt; 代理，实现可复现构建。&lt;/p&gt;
&lt;p&gt;对于 C++ 开发者，可以把它理解为「&lt;strong&gt;CMake + Conan/vcpkg + 包清单 + 锁文件&lt;/strong&gt;的四合一」：&lt;code&gt;go.mod&lt;/code&gt; ≈ &lt;code&gt;CMakeLists.txt&lt;/code&gt; + &lt;code&gt;conanfile.txt&lt;/code&gt;，&lt;code&gt;go.sum&lt;/code&gt; ≈ 锁文件，&lt;code&gt;go get&lt;/code&gt; ≈ &lt;code&gt;conan install&lt;/code&gt;，&lt;code&gt;replace&lt;/code&gt; 指令 ≈ CMake 的本地路径引入。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：Go modules 不是「又一个包管理器」，而是&lt;strong&gt;语言官方、零配置文件&lt;/strong&gt;的依赖解决方案。理解 &lt;code&gt;go.mod&lt;/code&gt; 的四个指令（&lt;code&gt;module&lt;/code&gt; / &lt;code&gt;go&lt;/code&gt; / &lt;code&gt;require&lt;/code&gt; / &lt;code&gt;replace&lt;/code&gt;）就掌握了 90% 的日常操作。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;构建系统&lt;/td&gt;
&lt;td&gt;CMake / Makefile&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go build&lt;/code&gt;（内建）&lt;/td&gt;
&lt;td&gt;无需写构建脚本&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;依赖清单&lt;/td&gt;
&lt;td&gt;&lt;code&gt;conanfile.txt&lt;/code&gt; / &lt;code&gt;vcpkg.json&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.mod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;官方格式，随项目同时维护&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;依赖安装&lt;/td&gt;
&lt;td&gt;&lt;code&gt;conan install&lt;/code&gt; / &lt;code&gt;vcpkg install&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go get&lt;/code&gt; / &lt;code&gt;go mod tidy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;不装到系统，进模块缓存&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;锁文件&lt;/td&gt;
&lt;td&gt;Conan &lt;code&gt;conan.lock&lt;/code&gt;（可选）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go.sum&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;默认生成&lt;/strong&gt;，锁定每行依赖版本+校验和&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;本地路径依赖&lt;/td&gt;
&lt;td&gt;&lt;code&gt;target_link_libraries&lt;/code&gt; 指向源码目录&lt;/td&gt;
&lt;td&gt;&lt;code&gt;replace ... =&amp;gt; ../xxx&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;官方一等公民指令&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;语义化版本&lt;/td&gt;
&lt;td&gt;Conan &lt;code&gt;[requires] pkg/1.2.3&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;v1.2.3&lt;/code&gt;（标签含 &lt;code&gt;v&lt;/code&gt; 前缀）&lt;/td&gt;
&lt;td&gt;Go 的版本就是 git tag&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;代理/镜像&lt;/td&gt;
&lt;td&gt;自建 Artifactory / Nexus&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOPROXY&lt;/code&gt;（如 goproxy.cn）&lt;/td&gt;
&lt;td&gt;环境变量即可切换，无需配置仓库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;私有仓库&lt;/td&gt;
&lt;td&gt;CMake &lt;code&gt;FetchContent&lt;/code&gt; + SSH&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOPRIVATE&lt;/code&gt; + git&lt;/td&gt;
&lt;td&gt;绕过代理直连&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;缓存目录&lt;/td&gt;
&lt;td&gt;Conan 本地 cache&lt;/td&gt;
&lt;td&gt;&lt;code&gt;$GOPATH/pkg/mod&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;全局共享，只读&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vendor 机制&lt;/td&gt;
&lt;td&gt;把第三方源码拷进仓库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go mod vendor&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可选但常用，利于离线构建&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-module-与-gomod-三大字段"&gt;3.1 module 与 go.mod 三大字段&lt;/h3&gt;
&lt;p&gt;在项目根目录运行 &lt;code&gt;go mod init&lt;/code&gt; 生成 &lt;code&gt;go.mod&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>测试：单元、表格驱动、基准、覆盖率</title><link>https://www.sylgalaxy.xyz/posts/go-04-02/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-02/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的 GTest 到 Go testing 标准库：约定优于配置，表格驱动是 Go 的灵魂测试法&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 把测试框架内置为标准库 &lt;code&gt;testing&lt;/code&gt;，&lt;strong&gt;零配置&lt;/strong&gt;、约定驱动：文件以 &lt;code&gt;_test.go&lt;/code&gt; 结尾，函数名 &lt;code&gt;TestXxx(t *testing.T)&lt;/code&gt; 即被测对象。不需要 GTest 那样的宏和注册表，&lt;code&gt;go test&lt;/code&gt; 一条命令跑全部测试。&lt;/p&gt;
&lt;p&gt;C++ 开发者上手 GTest 要经历「链接 gtest、写 TEST 宏、配 CMake、起 runner」；Go 则是「建 &lt;code&gt;_test.go&lt;/code&gt;、写 &lt;code&gt;func TestXxx(t *testing.T)&lt;/code&gt;、&lt;code&gt;go test&lt;/code&gt;」。**表格驱动测试（table-driven tests）**是 Go 社区最推崇的测试形态——本质是把断言与数据分离，让测试用例变成一张表。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;testing&lt;/code&gt; 包只给了「基础骨架」（&lt;code&gt;t&lt;/code&gt; 的各种方法），断言与 mock 不内置——这是 Go 的极简哲学。但配合表格驱动 + 子测试 + 基准 + 覆盖率，能覆盖绝大多数项目需求。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;测试框架&lt;/td&gt;
&lt;td&gt;GoogleTest / Catch2（第三方）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;testing&lt;/code&gt; 标准库&lt;/td&gt;
&lt;td&gt;零依赖、零配置，&lt;code&gt;go test&lt;/code&gt; 即跑&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试文件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;test_xxx.cpp&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;xxx_test.go&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;命名约定即可被发现&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试用例&lt;/td&gt;
&lt;td&gt;&lt;code&gt;TEST(Suite, Name)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;func TestXxx(t *testing.T)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;编译期自动收集，无宏无注册&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;断言&lt;/td&gt;
&lt;td&gt;&lt;code&gt;EXPECT_EQ&lt;/code&gt; / &lt;code&gt;ASSERT_EQ&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Errorf&lt;/code&gt; / &lt;code&gt;t.Fatal&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Go 里就是普通方法调用&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;致命 vs 非致命&lt;/td&gt;
&lt;td&gt;ASSERT（终止）vs EXPECT（继续）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Fatal&lt;/code&gt;（终止）vs &lt;code&gt;t.Errorf&lt;/code&gt;（继续）&lt;/td&gt;
&lt;td&gt;语义一一对应&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;子测试&lt;/td&gt;
&lt;td&gt;SCOPED_TRACE 近似&lt;/td&gt;
&lt;td&gt;&lt;code&gt;t.Run(&amp;quot;name&amp;quot;, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;自带层级输出、可独立筛选运行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;表格驱动&lt;/td&gt;
&lt;td&gt;GTEST 参数化 P 复杂&lt;/td&gt;
&lt;td&gt;切片 + for 循环&lt;/td&gt;
&lt;td&gt;语言特性天然支持，无需框架&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基准测试&lt;/td&gt;
&lt;td&gt;Google Benchmark&lt;/td&gt;
&lt;td&gt;&lt;code&gt;BenchmarkXxx(b *testing.B)&lt;/code&gt; + &lt;code&gt;b.N&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;benchmark 内建&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;覆盖率&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-fprofile-arcs&lt;/code&gt; + gcov/lcov&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go test -cover&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一条命令带 HTML 输出&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;数据竞态检测&lt;/td&gt;
&lt;td&gt;TSan（需编译期开启）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go test -race&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;运行时内建，跨平台&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-单元测试最小形态"&gt;3.1 单元测试最小形态&lt;/h3&gt;
&lt;p&gt;在 &lt;code&gt;calc.go&lt;/code&gt; 旁边放 &lt;code&gt;calc_test.go&lt;/code&gt;：&lt;/p&gt;</description></item><item><title>常用工具 gofmt/vet/doc/交叉编译</title><link>https://www.sylgalaxy.xyz/posts/go-04-04-gofmt-vet-doc/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-04-gofmt-vet-doc/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 clang-format/clang-tidy/doxygen 到 Go 内建工具链：规范靠工具强制，而非风格文档&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 的工具链是「一个 &lt;code&gt;go&lt;/code&gt; 命令 + 若干子命令」的整体。&lt;code&gt;gofmt&lt;/code&gt; 统一代码格式、&lt;code&gt;go vet&lt;/code&gt; 做静态检查、&lt;code&gt;go doc&lt;/code&gt; 生成/查看文档、&lt;code&gt;go build&lt;/code&gt; 配合环境变量实现交叉编译。与 C++ 需要 &lt;code&gt;clang-format&lt;/code&gt; + &lt;code&gt;clang-tidy&lt;/code&gt; + &lt;code&gt;doxygen&lt;/code&gt; + 一堆脚本不同，&lt;strong&gt;Go 把规范内置&lt;/strong&gt;——&lt;code&gt;gofmt&lt;/code&gt; 的格式无人争论，因为唯一标准。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;gofmt&lt;/code&gt; 从 Go 项目诞生起就存在，&lt;code&gt;go fmt&lt;/code&gt; 只是 go 工具链对它的子命令封装，两者格式化结果一致；真正的工程价值是让「风格讨论」从代码评审里消失——C++ 团队为空格和括号开过的会，在 Go 里不存在。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;代码格式化&lt;/td&gt;
&lt;td&gt;clang-format（需 .clang-format 配置）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;gofmt&lt;/code&gt; / &lt;code&gt;go fmt&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;零配置&lt;/strong&gt;，官方唯一风格&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;静态检查&lt;/td&gt;
&lt;td&gt;clang-tidy / cppcheck&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go vet&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;内建，覆盖导入/函数调用等&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文档生成&lt;/td&gt;
&lt;td&gt;doxygen（注释标记 + 配置）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go doc&lt;/code&gt; + &lt;code&gt;godoc&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;注释即文档，无需单独构建&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;文档注释风格&lt;/td&gt;
&lt;td&gt;&lt;code&gt;///&lt;/code&gt;、块注释 + doxygen 指令&lt;/td&gt;
&lt;td&gt;成对注释（块首选）&lt;/td&gt;
&lt;td&gt;&lt;code&gt;// 名称 描述&lt;/code&gt; 约定，导出符号必须注释&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;交叉编译&lt;/td&gt;
&lt;td&gt;每平台一套交叉工具链/CI&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GOOS=linux GOARCH=amd64 go build&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;一条命令 + 环境变量&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;静态链接&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-static&lt;/code&gt; / 静态库手动组合&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CGO_ENABLED=0&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;默认即可产纯静态二进制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;精简体积&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-s&lt;/code&gt; strip 符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;-ldflags &amp;quot;-s -w&amp;quot;&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;编译期传递 linker 参数&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;依赖清理&lt;/td&gt;
&lt;td&gt;CMake/vcpkg 手工重配&lt;/td&gt;
&lt;td&gt;&lt;code&gt;go mod tidy&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;与工具链一体&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-gofmt--go-fmt官方格式"&gt;3.1 gofmt / go fmt：官方格式&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 查看差异（不修改）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -l . &lt;span style="color:#75715e"&gt;# 列出格式不达标的文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -d file.go &lt;span style="color:#75715e"&gt;# 输出 diff 视角的差异&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 覆盖写文件&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;gofmt -w file.go
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go fmt ./... &lt;span style="color:#75715e"&gt;# 等价于 gofmt -w，作用于当前包全部 .go&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# gofmt 不影响语义：只重排缩进、对齐、换行、导入块&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;关键规则（&lt;strong&gt;你不需要背，工具会改&lt;/strong&gt;）：&lt;/p&gt;</description></item><item><title>构建部署与 Docker 化</title><link>https://www.sylgalaxy.xyz/posts/go-04-05-docker/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-05-docker/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的动态库/libtool 部署噩梦到 Go 的静态二进制：一个文件搞定容器化&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 编译产出&lt;strong&gt;静态二进制&lt;/strong&gt;（前提下 &lt;code&gt;CGO_ENABLED=0&lt;/code&gt;），没有动态库依赖、没有运行时安装（对比 C++ 的 &lt;code&gt;.so&lt;/code&gt;/&lt;code&gt;.dll&lt;/code&gt; + 运行时动态链接）。这让部署模型极简：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;go build&lt;/code&gt; → 一个可执行文件&lt;/li&gt;
&lt;li&gt;多阶段 Dockerfile（&lt;strong&gt;builder 编译 → 肥镜像剥离 → 瘦镜像运行&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;scratch&lt;/code&gt;/&lt;code&gt;alpine&lt;/code&gt; 镜像，体积通常 &lt;strong&gt;10~30MB&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;docker run&lt;/code&gt; / Compose 编排&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;C++ 部署的经典烦恼——&lt;code&gt;libstdc++.so.6 not found&lt;/code&gt;、&lt;code&gt;GLIBC_2.34 not found&lt;/code&gt;、ldconfig、需要把一堆 &lt;code&gt;.so&lt;/code&gt; 一起拷走——在纯 Go 世界里直接消失。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：静态编译 + 多阶段构建演示了 Go 的部署哲学：「&lt;strong&gt;产物单一、环境无关&lt;/strong&gt;」。只要你控制好 CGO 开关，一个二进制能跑在任意 Linux 上。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;构建产物&lt;/td&gt;
&lt;td&gt;动态库/静态库 + 可执行文件&lt;/td&gt;
&lt;td&gt;单一可执行文件&lt;/td&gt;
&lt;td&gt;无 &lt;code&gt;.so&lt;/code&gt;/&lt;code&gt;.a&lt;/code&gt; 需分发&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;运行时依赖&lt;/td&gt;
&lt;td&gt;目标机需匹配 libc/动态库&lt;/td&gt;
&lt;td&gt;&lt;code&gt;CGO_ENABLED=0&lt;/code&gt; 时零依赖&lt;/td&gt;
&lt;td&gt;拷贝即运行&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;版本冲突&lt;/td&gt;
&lt;td&gt;&lt;code&gt;GLIBC_2.30 not found&lt;/code&gt;、&lt;code&gt;.so&lt;/code&gt; 名冲突&lt;/td&gt;
&lt;td&gt;无（Go 自带运行时）&lt;/td&gt;
&lt;td&gt;彻底告别 ABI 地狱&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;镜像方案&lt;/td&gt;
&lt;td&gt;手动装依赖/多级 COPY .so&lt;/td&gt;
&lt;td&gt;多阶段：build → scratch/alpine&lt;/td&gt;
&lt;td&gt;一条 &lt;code&gt;FROM ... AS builder&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;镜像体积&lt;/td&gt;
&lt;td&gt;常见 500MB~2GB&lt;/td&gt;
&lt;td&gt;常见 10~30MB&lt;/td&gt;
&lt;td&gt;静态二进制省掉一层层库&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;基础镜像&lt;/td&gt;
&lt;td&gt;ubuntu/debian 全量&lt;/td&gt;
&lt;td&gt;&lt;code&gt;scratch&lt;/code&gt;（空镜像）/ &lt;code&gt;alpine&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;可以空到极致&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;健康检查&lt;/td&gt;
&lt;td&gt;手写探针/脚本&lt;/td&gt;
&lt;td&gt;&lt;code&gt;HEALTHCHECK&lt;/code&gt; + HTTP /healthz&lt;/td&gt;
&lt;td&gt;Dockerfile 指令&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;服务发现/编排&lt;/td&gt;
&lt;td&gt;systemd / 手动进程管理&lt;/td&gt;
&lt;td&gt;同样 systemd，但容器内单进程&lt;/td&gt;
&lt;td&gt;容器化程度完全可控&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;部署步骤&lt;/td&gt;
&lt;td&gt;装库 → 拷二进制 → 起服务&lt;/td&gt;
&lt;td&gt;跑镜像&lt;/td&gt;
&lt;td&gt;镜像即交付物&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-go-build-产物静态优先"&gt;3.1 go build 产物：静态优先&lt;/h3&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 常见部署编译命令（Linux amd64、静态、精简符号）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;CGO_ENABLED&lt;span style="color:#f92672"&gt;=&lt;/span&gt;&lt;span style="color:#ae81ff"&gt;0&lt;/span&gt; GOOS&lt;span style="color:#f92672"&gt;=&lt;/span&gt;linux GOARCH&lt;span style="color:#f92672"&gt;=&lt;/span&gt;amd64 &lt;span style="color:#ae81ff"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;go build -ldflags &lt;span style="color:#e6db74"&gt;&amp;#34;-s -w&amp;#34;&lt;/span&gt; -o app ./cmd/server
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 产物检查（Linux 上）&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;file app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# app: ELF 64-bit LSB executable, x86-64, statically linked&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 确认没有动态链接&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;ldd app
&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#75715e"&gt;# 不是 a dynamic executable&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;C++ 对照&lt;/strong&gt;：C++ 默认生成动态链接可执行文件，目标机必须带好 &lt;code&gt;.so&lt;/code&gt; 与匹配的 libc 版本；Go 默认（cgo 关）就是&lt;strong&gt;静态链接&lt;/strong&gt;。代价与取舍见 3.3。&lt;/p&gt;</description></item><item><title>项目结构 internal/pkg/cmd</title><link>https://www.sylgalaxy.xyz/posts/go-04-03-internal-pkg-cmd/</link><pubDate>Tue, 13 Oct 2026 00:00:00 +0000</pubDate><guid>https://www.sylgalaxy.xyz/posts/go-04-03-internal-pkg-cmd/</guid><description>&lt;blockquote&gt;
&lt;p&gt;从 C++ 的目录与命名空间组织到 Go 的「包即边界」：cmd/internal/pkg 是社区事实标准&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="一简述"&gt;一、简述&lt;/h2&gt;
&lt;p&gt;Go 没有 C++ 头文件/源文件对，也没有 C++ 那种「目录 + 命名空间」两级组织。Go 的组织单位是&lt;strong&gt;包（package）&lt;/strong&gt;，一个目录一个包，&lt;code&gt;import&lt;/code&gt; 路径即模块路径 + 目录路径。一个可发布的 Go 项目结构，社区多年沉淀出了事实标准：&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;&amp;lt;repo&amp;gt;
├── cmd/ # 可执行程序入口（main 包）
├── internal/ # 私有代码：仅本项目可导入
├── pkg/ # 可复用库代码：对外公开
├── configs/ # 配置文件
├── scripts/ # 构建/运维脚本
└── go.mod
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;更向上看，Go 的哲学是 &lt;strong&gt;「包即层级」&lt;/strong&gt;：包之间靠 import 建立依赖，import 循环会被编译器直接拒绝——比 C++ 的循环 include 报错更早、更严格。这天然强制了「按层依赖」的架构。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;核心要点&lt;/strong&gt;：&lt;code&gt;cmd&lt;/code&gt; / &lt;code&gt;internal&lt;/code&gt; / &lt;code&gt;pkg&lt;/code&gt; 不是语言强制，而是 golang-standards/project-layout 提出的&lt;strong&gt;事实约定&lt;/strong&gt;。真正由 Go 强制的是：&lt;code&gt;internal&lt;/code&gt; 的可见性规则、每个 &lt;code&gt;main&lt;/code&gt; 包是入口、包不能循环导入。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr&gt;
&lt;h2 id="二c-对照速查表"&gt;二、C++ 对照速查表&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;概念&lt;/th&gt;
&lt;th&gt;C++&lt;/th&gt;
&lt;th&gt;Go&lt;/th&gt;
&lt;th&gt;关键差异&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;组织单位&lt;/td&gt;
&lt;td&gt;命名空间（namespace）+ 头文件&lt;/td&gt;
&lt;td&gt;包（package）&lt;/td&gt;
&lt;td&gt;目录=包=导入路径，三合一&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;入口&lt;/td&gt;
&lt;td&gt;&lt;code&gt;int main()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;package main&lt;/code&gt; + &lt;code&gt;func main()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;main 包即程序入口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;公共接口&lt;/td&gt;
&lt;td&gt;&lt;code&gt;namespace Foo&lt;/code&gt; 内公开符号&lt;/td&gt;
&lt;td&gt;大写导出 / 小写私有&lt;/td&gt;
&lt;td&gt;可见性跟&lt;strong&gt;标识符首字母&lt;/strong&gt;走&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;私有代码&lt;/td&gt;
&lt;td&gt;pimpl / 内部命名空间 / 隐藏符号&lt;/td&gt;
&lt;td&gt;&lt;code&gt;internal/&lt;/code&gt; 目录&lt;/td&gt;
&lt;td&gt;语言级可见性守卫&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;循环依赖&lt;/td&gt;
&lt;td&gt;前置声明 + 复杂 include 图&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;编译器拒绝&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;包循环导入即编译错误&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;头文件&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.h&lt;/code&gt; 声明 + &lt;code&gt;.cpp&lt;/code&gt; 实现&lt;/td&gt;
&lt;td&gt;一个 &lt;code&gt;.go&lt;/code&gt; 文件即包的一段&lt;/td&gt;
&lt;td&gt;无头文件，声名即定义&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;分层&lt;/td&gt;
&lt;td&gt;module/backend/… 手工约定&lt;/td&gt;
&lt;td&gt;handler→service→repository&lt;/td&gt;
&lt;td&gt;由 import 依赖方向强制&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;单一大包&lt;/td&gt;
&lt;td&gt;一个巨型头文件库&lt;/td&gt;
&lt;td&gt;拆小而聚焦的包&lt;/td&gt;
&lt;td&gt;Go 鼓励多包、小接口&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;测试辅助&lt;/td&gt;
&lt;td&gt;测试私有符号靠 friend/内部类&lt;/td&gt;
&lt;td&gt;&lt;code&gt;internal&lt;/code&gt; 包可见&lt;/td&gt;
&lt;td&gt;测试可直接放同包访问私有函数&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;h2 id="三逐主题详解"&gt;三、逐主题详解&lt;/h2&gt;
&lt;h3 id="31-标准布局总览cmd--internal--pkg"&gt;3.1 标准布局总览：cmd / internal / pkg&lt;/h3&gt;
&lt;p&gt;以 golang-standards/project-layout 为参考的常见布局：&lt;/p&gt;</description></item></channel></rss>