在 Go 1.27.1 里实测 context.Value:字符串 key 会被另一个包覆盖,自定义类型 key 互不干扰;查找沿父链线性往上找,1000 层时查最里层的 key 要 1331 ns、查最外层仍是 3–9 ns;每次 WithValue 一次分配;取回的是 any,断言错类型会 panic;并摘录文档和 value 函数源码。
在 Go 1.27.1 里验证 time.Time 的单调时钟读数:time.Now() 的 String 带 m=+…;Add 保留、AddDate/Round/Truncate/UTC/Local/In 都去掉;t == t.Round(0) 是 false 而 Equal 是 true,JSON 往返、map key、不同时区都有类似的坑;time.Now() 32 ns,time.Since 15 ns;并摘录文档里关于何时用单调读数的规则。
在 Go 1.27.1 里验证时区的坑:跨夏令时 Add(24h) 与 AddDate 差 1 小时,不存在的 2:30 得到 01:30 EST,重复的 1:30 取先出现的 EDT;Parse 不带时区按 UTC、带 EST 缩写偏移为 0;LoadLocation 每次 17498 ns;TZ 环境变量决定 Local;没有 tzdata 的容器里 LoadLocation 失败,-tags timetzdata 只多 381 KiB。
在 Go 1.27.1 里实测 net/http 服务端:一个连接依次经历 new → active → idle → active → idle → closed;500 个连接让 goroutine 增加 1000(每个连接约 2 个,因为 Handler 运行期间还有后台读 goroutine);小响应自动带 Content-Length,Flush 或大响应用 chunked;Handler panic 只关闭当前连接、不会让进程崩溃;客户端断开会立即取消 r.Context()。
在 Go 1.27.1 里实测 http.Client 连接池:读完并关闭响应体时 20 个请求只用 1 个连接,不读也不关会新建 20 个连接并多出 60 个 goroutine;MaxIdleConnsPerHost 默认 2,20 个并发请求后第二波又新建 18 个连接;每个请求新建一个 Transport 会累积 50 个连接和 150 个 goroutine;DefaultClient 没有超时。
在 Go 1.27.1 里逐个验证 HTTP 超时:不设 ReadHeaderTimeout 时半个请求头能占着连接 3 秒以上,设了 200 ms 就被关;WriteTimeout 不会取消 Handler;IdleTimeout 回收空闲连接;TimeoutHandler 100 ms 返回 503;客户端的 Client.Timeout 和 ctx 会截断慢速响应体(3 字节),ResponseHeaderTimeout 不会(10 字节读完)。
在 Go 1.27.1 里实测 HTTP/2:默认 TLS 自动用 h2,但自定义 TLSClientConfig 的 Transport 要加 ForceAttemptHTTP2;同一个 tls.Config 被多个 Transport 共用时,第一个把 NextProtos 改成 [h2 http/1.1],第二个会报 malformed HTTP response;用 Protocols 可以跑明文 h2c;300 个并发请求下,HTTP/2 默认预热后仍新增约 50 个 TCP 连接,服务端把流上限设成 10 会让用时涨到 1.2–3.3 秒。
在 Go 1.27.1 里比较测试 HTTP handler 的三种方式:ResponseRecorder(1509 ns,不经过网络)、httptest.NewServer(真实回环端口,45998 ns)、httptest.NewTestServer(内存网络,13320 ns);Recorder 没有 Content-Length、panic 会传进测试、静默忽略第二次 WriteHeader;NewTestServer 的 URL 是 example.com,ts.Client() 访问任意地址都到达它。
在 Go 1.27.1(arm64 macOS)里验证 io.Copy:默认 32 KiB 缓冲区,目标是 io.Discard 时因为它自带 ReadFrom 变成 8 KiB;优先走 WriterTo、其次 ReaderFrom、最后才是缓冲区循环;文件到 TCP 走接口 57 ms,隐藏接口后 109 ms,而文件到文件在这台机器上没有差别(83 对 79 ms);LimitReader 会把缓冲区缩小。
在 Go 1.27.1(arm64 macOS)里量 bufio 的缓冲区大小:50 万次 16 字节小写不缓冲要 976.5 ms(50 万次系统调用),默认 4096 字节的 bufio.Writer 只要 6.0 ms(1954 次),64 KiB 以上收益趋平;忘了 Flush 丢了 3712 字节而不报错;逐字节读 128 MiB,16 字节缓冲区 3865.6 ms,4 KiB 起约 280 ms;默认 Scanner 遇到超过 64 KiB 的行会停下。
在 Go 1.27.1(macOS)里实测 os/exec 的陷阱:不 Wait 会留下状态 Z 的僵尸进程;先 Wait 再读 StdoutPipe 报 file already closed;管道写满且没人读时 Wait 一直不返回;孙进程抱着 stdout 会让 Output 多等约 1 秒,设 WaitDelay 200 ms 后 206 ms 返回(ErrWaitDelay);CommandContext 的 200 ms 超时只杀直接子进程,实际约 2 秒后才返回;启动一个进程约 2.1 ms。
在 Go 1.27.1(macOS)里实测优雅退出:不处理 SIGTERM 时,2 秒的在途请求 0.51 秒后被断开;用 signal.NotifyContext + Server.Shutdown 时,在途请求 2.00 秒后正常完成、新连接被拒绝、进程 1.63 秒后以 0 退出;Shutdown 超时 500 ms 时请求被截断并返回 context deadline exceeded;被 Hijack 的连接 Shutdown 不会等。