time.Ticker 在股票轮询中易漏更新,因其 Tick 是准时触发而非执行完再等待;若单次请求超时,后续 Tick 会被丢弃;应优先用 time.Sleep 控制节奏,或配合 select+default/缓冲 channel 防阻塞,并设置 http.Client 超时及连接池参数,严格校验错误与 JSON 解析逻辑,杜绝 goroutine 泄露。

为什么 time.Ticker 在股票轮询里容易漏掉更新
因为 ticker 的每次 Tick 是“准时触发”,不是“执行完再等”。如果一次 HTTP 请求 + 解析耗时超过间隔(比如 5s 间隔但某次请求卡了 6s),下一次 tick 就会直接丢弃,不会排队补上。
- 用
time.Sleep替代time.Ticker更可控:每次做完完整逻辑再睡,避免堆积或跳过 - 如果坚持用
time.Ticker,必须配合select+default或带缓冲的 channel 防止阻塞主循环 - 真实行情接口(如 Yahoo Finance、Alpha Vantage)常有速率限制,硬扛高频 ticker 可能直接被 429 拦住,反而不如固定 sleep + 错误重试稳
如何用 http.Client 设置超时避免 goroutine 泄露
没设超时的 http.Get 在网络卡死时会永久挂起 goroutine,监控程序跑几天后 goroutine 数暴涨是典型症状。
- 必须用带
Timeout的http.Client,而不是默认 client:client := &http.Client{Timeout: 10 * time.Second} - 别只设
Timeout,生产环境建议拆开设:Transport的IdleConnTimeout和MaxIdleConnsPerHost防连接池膨胀 - 错误检查不能只看
err != nil,要区分url.Error中的Timeout()和真实业务错误(如 401 API key 失效)
json.Unmarshal 解析股价数据时 panic 的三个常见原因
从 API 拿到的 JSON 字段名大小写、嵌套层级、空值处理稍有偏差,json.Unmarshal 就可能静默失败或 panic,尤其在结构体字段没加 json: tag 时。
- 所有 float 字段(如
Price、Change)必须用float64,别用int或string—— 即使文档说“整数”,实际返回可能是"123.45"或null - 嵌套对象(如
Meta、TimeSeries)务必用指针字段:*TimeSeriesData,否则null值会导致 unmarshal 失败 - 先用
json.RawMessage接原始字节,打印出来确认结构,再映射——别信文档,信你抓到的 response body
goroutine 泄露比 CPU 高更难发现,但更致命
一个没回收的 goroutine 占不了多少 CPU,但内存和 fd 会持续累积。跑一周后 runtime.NumGoroutine() 从 5 增到 2000+,而 top 看不出异常。
立即学习“go语言免费学习笔记(深入)”;
- 每启动一个 goroutine,必须明确它的退出路径:要么有
donechannel 控制,要么有明确的 return 条件 - HTTP 轮询场景下,别在 goroutine 里直接
for { ... time.Sleep() },要用for select { case - 上线前加一行日志:
log.Printf("goroutines: %d", runtime.NumGoroutine()),每分钟打一次,异常增长立刻可见
异步轮询真正麻烦的从来不是并发本身,而是每个环节的“不完全退出”——超时没关连接、channel 没 close、goroutine 没响应 cancel。这些点串起来,就是半夜三点收到告警的原因。










