Go HTTP Body 为什么只能读一次?
Go 的 HTTP Body 本质上是一次性消费的数据流,读完就会移动到末尾,因此日志中间件读过后再解 JSON 常见直接得到 EOF。本文从服务端恢复 r.Body、客户端借助 GetBody 重放请求,到生产环境中的大小限制、脱敏和幂等边界,梳理这类问题的正确处理方式。
Go 的 HTTP Body 本质上是一次性消费的数据流,读完就会移动到末尾,因此日志中间件读过后再解 JSON 常见直接得到 EOF。本文从服务端恢复 r.Body、客户端借助 GetBody 重放请求,到生产环境中的大小限制、脱敏和幂等边界,梳理这类问题的正确处理方式。

在 CentOS 上部署 Go 应用时,安全问题不能只盯着业务代码。本文按系统加固、应用防护、编码与运行时实践、持续维护四个层面梳理关键配置,保留常用命令与代码示例,帮助你快速判断哪些措施适合立即落地。

Go 1.24 新增的 `runtime.AddCleanup`,把“观察对象生命周期”和“执行资源释放”拆开,减少了 `SetFinalizer` 常见的对象复活、引用环和依赖顺序问题。但它依旧不是确定性析构,真正可靠的释放路径仍然是 `Close` 加 `defer`。 文件句柄、Socket 和 C 内存这类资源,一旦调用方漏掉 `Close`,就可能把问题拖成真正的泄漏。

在 Go 并发里,把 channel 变量设为 nil 是一种很实用的 select 控制手段。它不需要额外语法,却能在同一套循环中动态启停接收、发送和多路合并分支。关键在于分清 nil、关闭 channel 与 default 忙循环的边界,才能既简化状态机,又避免死锁和空转。

Go 并发测试里常见的 `time.Sleep` 看似简单,实际既拖慢执行,也会把测试结果交给机器负载和调度时机。随着 Go 1.25 将 `testing/synctest` 纳入稳定标准库,开发者可以用虚拟时间和明确同步点重写超时、定时器与异步逻辑测试。

Go 1.26 为 reflect.Type 和 reflect.Value 新增了 Fields 方法,把结构体字段遍历从“按索引取值”改成了更直接的迭代写法。它解决的是可读性和组织方式问题,不改变反射原有的可设置性、导出规则、嵌入字段处理方式,也不默认带来性能提升。

Go 1.26 补上了 `signal.NotifyContext` 在退出诊断上的关键短板:程序因系统信号取消时,开发者终于能通过 `context.Cause` 看见具体原因,而不再只有模糊的 `context canceled`。这让服务优雅退出、日志排障和信号处理边界都更容易说清。

Go 1.26 新增的 ArtifactDir,把测试产物的保存位置、生命周期和保留方式统一了起来。它适用于普通测试、基准测试和模糊测试,既能避免项目目录被临时文件污染,也方便在本地或 CI 中留下失败现场。

GOMAXPROCS 常被误解为“限制 goroutine 数量”或“固定 CPU 核数”,在容器里更容易因为宿主机与配额不一致而配错。结合 Go 1.25 之后的新默认行为,本文梳理它到底控制什么、何时不用再手动设,以及哪些场景仍应基于压测与指标做显式调整。

在 Go 里,`resp.Body.Close()` 不是可有可无的习惯写法,而是 `net/http` 明确交给调用方完成的收尾责任。真正容易混淆的是:关闭响应体解决的是资源释放,想让 HTTP/1.x 连接更有机会复用,通常还需要把响应读到 EOF。

Go 切片传参后执行 append,结果之所以“有时影响外层、有时又不影响”,关键不在“引用类型”或“值传递”这类单句判断,而在切片头复制与底层数组复用。本文用几个短例子讲清 len、cap 和共享数组的关系,并给出业务代码里更稳妥的写法。

Go 里切片不能直接用 `==` 比较,真正麻烦的是该在 `reflect.DeepEqual`、手写循环和 `slices.Equal` 之间怎么选。结合 Go 1.23.6 基准测试数据来看,`slices.Equal` 基本拿到了手写循环的性能,同时保留了更好的通用性,反射方案则更适合少数需要严格语义或动态结构兜底的场景。
