go适合高并发网络服务,因其调度模型和net/http等标准库深度优化;但不适合脚手架或胶水脚本,因编译部署流程长、缺乏热重载支持。

适合做高并发网络服务,但别拿来写脚手架或胶水脚本
Go 的核心优势在调度模型和标准库对网络 I/O 的深度优化,不是语法多简洁。它天生适合长期运行、连接数多、逻辑相对清晰的服务端程序,比如 API 网关、消息中转、实时同步服务。反过来,如果项目需要快速试错、频繁调用外部 CLI、依赖大量动态加载插件,Go 反而拖慢节奏——编译、打包、调试链路比 Python/JS 长得多。
常见错误现象:go run main.go 启动慢得反常,或者热重载靠 air 或 reflex 还是卡顿;本质是 Go 不鼓励“边改边跑”的开发流,它预设的场景是“构建一次,部署稳定”。
- Web API / RPC 服务:用
net/http或gin、echo没问题,但别指望靠中间件堆出 Rails 那种生态 - CLI 工具:可以做,但参数解析、颜色输出、交互式提示要自己补很多轮子(
spf13/cobra是事实标准,但配置成本比argparse高) - 数据管道 / ETL:适合固定格式、高吞吐场景(如日志转发),不适合字段频繁变更、需 SQL 交互的轻量分析
GC 压力小不等于内存无坑,切片和 map 是高频泄漏点
Go 的 GC 确实比 Java 轻量,但开发者对内存生命周期的控制变弱了——尤其是 []byte、map[string]interface{} 这类结构,稍不注意就让旧数据被新 slice 引用住,导致整块底层数组无法回收。
典型表现:服务运行几小时后 RSS 持续上涨,pprof heap 显示大量 runtime.mspan 或 reflect.Value 占用,但代码里没明显 new。
- 切片截取后别直接返回子切片:用
append([]T{}, s[i:j]...)复制一份,避免持有原底层数组 - map 删除键后记得
delete(m, key),别只置nil;更关键的是,别把 map 当缓存用而不设限(没 TTL、没 size 控制) - HTTP handler 里别把
req.Body读到全局变量或长生命周期结构体里——它背后是io.ReadCloser,关联着连接缓冲区
goroutine 泄漏比 panic 更难发现,超时和 context 是唯一解药
一个没加 context.WithTimeout 的 http.Client 调用,或一个没监听 ctx.Done() 的 for-select 循环,可能让 goroutine 永远挂起。它们不报错、不 crash,只悄悄吃掉栈内存和调度开销,直到 runtime: goroutine stack exceeds 1000000000-byte limit 才崩。
使用场景:微服务间调用、数据库查询、第三方 API 请求——只要涉及阻塞等待,就必须有退出机制。
- 所有
http.Client.Do必须配context,不要用client.Get(url)这种无 timeout 的快捷方式 - 启动 goroutine 前先检查
ctx.Err() != nil,循环里每次 select 都要带case - 用
go tool trace查泄漏比看 pprof 更直接:搜goroutine状态,找长期处于running或syscall却没进展的实例
交叉编译方便,但 CGO 和系统库会突然打破幻想
GOOS=linux GOARCH=arm64 go build 能直接打出 Linux ARM 包,前提是没碰 CGO。一旦用了 cgo(比如连 PostgreSQL、SQLite、OpenSSL),编译就强依赖目标平台的 C 工具链和头文件。本地 macOS 编译 Linux 二进制?大概率卡在 gcc: error: unrecognized command-line option ‘-m64’。
性能影响:启用 CGO 后,goroutine 调度器对 C 调用不可见,可能触发 M:N 线程切换,吞吐下降 10%~30%;兼容性上,Alpine 镜像默认没 glibc,而多数 CGO 依赖它。
- 优先选纯 Go 驱动:PostgreSQL 用
jackc/pgx(非lib/pq),SQLite 用mattn/go-sqlite3的CGO_ENABLED=0模式(功能略减,但够用) - 必须用 CGO 时,用
golang:alpine镜像要装musl-dev,用golang:debian则装gcc和对应 -dev 包 - Docker 构建加
BUILDKIT=1和--platform linux/arm64,比本地交叉编译更稳
真正麻烦的从来不是语法或工具链,而是当你在 goroutine 里开了个 timer,又忘了在 context cancel 时 stop 它——这种泄漏不会立刻暴露,但会在凌晨三点让你手机震醒。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











