CLI 工具 flag 与 cobra

从 C++ 的 Boost.Program_options / CLI11 到 Go:标准库 flag 包入门,再上手 cobra 这个事实标准的命令行框架 一、简述 命令行工具(CLI)是 Go 最擅长的领域之一:编译出来是单一静态二进制,启动快、分发简单,天然适合写 git / docker 这类开发者工具。Go 在命令行的「外挂」上做了很多设计——os.Args 给你原始参数,标准库 flag 包给你简单的 -name value 解析,而 spf13/cobra(Kubernetes、Hugo、Docker CLI 大量使用)则提供子命令、flag 继承、自动帮助和 shell 补全的完整方案。 核心要点:C++ 里解析命令行要么手写循环扫 argv,要么拉 Boost.Program_options / CLI11;Go 的路径是「标准库 flag 够用即用,复杂命令行直接上 cobra」。cobra 的「命令树」思想对 C++ 开发者来说很像「用对象组合搭一棵命令路由树」。 二、C++ 对照速查表 概念 C++ Go 关键差异 入口参数 int main(int argc, char* argv[]) func main() + os.Args os.Args[0] 是程序名,Go 是切片可遍历 参数解析库 Boost.Program_options / CLI11 flag(标准库) flag 零依赖,但功能简单 子命令框架 自己搭 / CLI11 github.com/spf13/cobra cobra 是事实标准(k8s/gh/hugo 都用) 类型自动转换 boost::lexical_cast flag 绑定即转换 flag.Int 自动转,无需显式 cast 帮助文本 手动拼接打印 flag / cobra 自动生成 -h / --help 开箱即用 长短选项 -v / --verbose -v / --verbose 等价 flag 单双横线都认;布尔无需值 子命令树 无标准方案 cobra AddCommand 层层挂载 命令即对象,可嵌套 shell 补全 无标准方案 cobra completion 命令 生成 bash/zsh/fish 脚本 解析失败行为 抛异常 / 返回错误码 flag 默认 ExitOnError 可切换到 ContinueOnError 自己处理 三、逐主题详解 3.1 os.Args —— 原始参数切片 任何命令行的起点。和 C++ 的 argc/argv 相比,Go 把它做成了普通切片,不用数个数、不用指针算术: ...

2026 年 10 月 13 日

Web 框架 Gin / Echo

从 C++ 的 Crow / Drogon 到 Go:Gin 是什么、何时该用它,以及它替你省下的那些 net/http 样板代码 一、简述 上一篇我们把 net/http 摸了一遍——纯标准库完全能写服务,但路由到参数、JSON 绑定校验、中间件这些「每个项目都要重复一遍」的活,写得多了就烦。Gin 和 Echo 是 Go 生态里最主流的两个 Web 框架,它们把「路由分组 + 参数绑定 + 校验 + 中间件」整合成统一 API。Gin 以高性能(基于 radix tree 的路由器)和极简 API 出名,Echo 结构更规整、前后端感触更「框架味」。 核心要点:框架不改变 Go 的 Web 本质——底层还是 http.Handler;Gin/Echo 只是给你一个更顺手的 c *gin.Context / e echo.Context。「参数绑定 + binding tag 校验」是 C++ 框架(如 Drogon)很难优雅做到的事,Go 用结构体标签声明式解决,这是最大的体验提升点。 二、C++ 对照速查表 概念 C++ Go 关键差异 Web 框架 Crow / Drogon / cpp-httplib Gin / Echo Gin 性能强、Echo 规整 路由注册 CROW_ROUTE(app, "/x") r.GET("/x", fn) 链式+分组,表达力更强 路径参数 CROW_ROUTE(app,"/<int>") 回调参数 c.Param("id") 参数进 Handler 上下文 路由分组 手动前缀 r.Group("/api") 组内共享中间件/前缀 JSON 返回 app.route(...).post(...) 手动拼 c.JSON(200, obj) 一行返回+自动 Content-Type 参数绑定 手写解析字段 c.ShouldBindJSON(&req) 结构体 tags 声明式映射 参数校验 手写 if 判断 binding:"required" tag 驱动,绑定即校验 中间件 手动包装 / 框架回调 r.Use(mw) 全局/组/路由三级粒度 panic 恢复 手动 try/catch gin.Recovery() 内置 框架默认就带 三、逐主题详解 3.1 Gin 起步 —— 一个能跑的 Hello 安装并写最小服务: ...

2026 年 10 月 13 日

数据库接入 database/sql · gorm · sqlx

从 C++ 的 sqlite3 / libpq + 手写 ORM 到 Go:database/sql 抽象层 + 驱动隔离,数据访问可以有一份标准答案 一、简述 Go 数据库世界的中心是 database/sql——一个驱动无关的 SQL 访问抽象层。就像 C++ 里 sqlite3_open、PQconnectdb 各写各的,Go 则约定「先 sql.Open 拿到抽象连接,然后 Query/Exec/事务全走同一套接口」,不同数据库只是换一个驱动 import 和连接串。sqlx 在其上补了「结构体 ↔ 行」的便捷映射;gorm 则是全功能 ORM(自动建表、关联、迁移),适合快速开发。三者是「底层 → 便捷 → 全自动」的一条谱系。 核心要点:先记住 database/sql 的三个纪律——连接池要调、行/stmt/tx 用后必关、占位符随驱动变化(MySQL 用 ?,PostgreSQL 用 $1)。在这之上,sqlx 与 gorm 都是锦上添花。 二、C++ 对照速查表 概念 C++ Go 关键差异 数据库接口 sqlite3.h / libpq 各一套 database/sql 标准库 统一抽象,换库只换驱动/连接串 连接池 自己写 thread pool sql.DB 自带 + SetMaxOpenConns 连接池是 DB 的默认行为 查询单行 sqlite3_step + 手动取列 db.QueryRow(...).Scan(&v) Scan 一次到位 查询多行 每列手动转换 rows.Next() + rows.Scan 循环+Scan,模板化 预处理 sqlite3_prepare_v2 db.Prepare + stmt.Exec 语义一致,但事务内惯用 tx 级 prepare 事务 BEGIN/COMMIT/ROLLBACK db.Begin() + tx.Commit/Rollback 要 defer tx.Rollback() 做兜底 结构体映射 手写行→struct 拷贝 sqlx Get/Select 自动映射 tag db:"col" 声明式 ORM 手写/第三方(如 sqlpp11) GORM(AutoMigrate/关联) 自动建表、crud、迁移 错误处理 返回码 err != nil 全链路 每步都要查 三、逐主题详解 3.1 database/sql 起步 —— Open 与连接池 sql.Open 并不会真的连数据库(Ping 才触发真实连接),它返回的 *sql.DB 是一个连接池句柄: ...

2026 年 10 月 13 日

原生 HTTP 服务 net/http

从 C++ 的 Boost.Beast / Crow 到 Go:标准库就是一套完整的 HTTP 服务器,Handler 即函数签名 一、简述 在 C++ 里写 HTTP 服务要选库(Boost.Beast 偏底层、Crow 要自己搭路由、Drogon 大而全),而在 Go 里标准库 net/http 就是一个能上生产的基础 HTTP 服务框架——路由、请求解析、响应写出、超时控制、优雅关闭全都有。它的核心哲学是「一个 http.Handler 就是一个 http.ResponseWriter 参数 + 一个 *http.Request 参数的函数」,一切中间件、路由、框架都是这个接口的装饰与组合。 核心要点:Handler 是唯一的核心接口。Go 1.22 起 http.ServeMux 原生支持「方法 + 路径」路由("GET /users/{id}"),标准库写 REST 服务不再需要任何第三方框架。 二、C++ 对照速查表 概念 C++ Go 关键差异 HTTP 库 Boost.Beast / Crow / Drogon / cpp-httplib net/http 标准库 开箱即用,零依赖起服务 处理器 继承 handler / 回调 http.Handler 接口 + http.HandlerFunc 函数签名即处理器 路由 Crow 手动匹配 / router 库 http.NewServeMux Go 1.22+ 支持方法路由 路径参数 :id 需框架支持 r.PathValue("id") ServeMux 通配符 {id} 服务对象 Crow::run() http.Server 结构体 超时/监听全是 Server 字段 会话/keep-alive 手管 socket 自动,IdleTimeout 管空闲连接 默认开启 JSON 响应 序列化库 + 手动 header json.NewEncoder(w).Encode(v) 一行流式写出 中间件 手写装饰器 / Crow 外挂 func(http.Handler) http.Handler 纯函数包裹,标准模式 优雅关闭 自行实现 srv.Shutdown(ctx) 标准库内置,等待在飞请求 三、逐主题详解 3.1 最小 HTTP 服务 —— Handler 与 HandlerFunc 任何 HTTP 服务都绕不开这两个类型: ...

2026 年 10 月 13 日

综合项目实战记录(短链接服务)

把前面四篇的东西缝合起来:一个「从需求到 Docker 部署」的完整短链接服务,走一遍 Go 工程化的真实流程 一、简述 短链接服务是一个完美的「毕业设计」:需求明确、覆盖路由/存储/并发/测试/构建全链路、不引入任何第三方 Web 框架也能跑(正适合巩固 net/http)。本文按真实开发顺序走:需求分析 → 目录设计 → 存储接口 → 短码生成 → HTTP 路由 → 计数 → 单元测试 → go mod → 构建与 Docker。 核心要点:这个项目刻意只用标准库写 HTTP(把 02-原生HTTP服务-net-http 练扎实),存储接口先给内存实现、日后可平移到 04-数据库接入-database-sql-gorm-sqlx 的 database/sql/gorm。它演示的是 Go 工程化的结构:cmd/ 装入口、internal/ 装业务、store 是抽象边界。 二、C++ 对照速查表 概念 C++ Go 关键差异 工程布局 src/ + CMake targets cmd/ + internal/ 目录即包,internal 强制隔离 抽象接口 抽象基类/接口类 interface{} 接口(store.URLStore) 鸭子类型式,一个接口多个实现 短码生成 自写 base62 自写(本项目实现) 逻辑两端一致,关注冲突处理 重定向 手写响应头 Location http.Redirect(w, r, url, 302) 标准库一行 并发安全 std::mutex / std::atomic sync.RWMutex + map 读写锁分离,并发读不死锁 单元测试 gtest/test framework testing + go test table-driven 是惯例 构建 CMake/ninja go build ./cmd/server 单二进制,静态链接 容器化 手写 Dockerfile 依赖编译环境 golang builder 镜像 + 多阶段 官方镜像成熟,CGO 关掉即纯静态 三、逐主题详解 本项目按「需求 → 结构 → 代码 → 测试 → 构建 → 部署」的顺序推进,每一小步都有可直接运行的代码片段。 ...

2026 年 10 月 13 日