必须用显式配置的http.client设timeout(推荐8秒)、连接池参数,并严格按平台要求拼签名、校验响应体code字段,否则易因超时、签名错或误判200状态导致失败。

别用 http.Post 直接发,90% 的失败都卡在超时没设、签名拼错、响应没判对这三处。
用 http.Client 显式控制超时和重试
裸调 http.Post 会继承 http.DefaultClient 的无限超时,一旦服务商响应慢或网络抖动,goroutine 就卡死不释放。线上服务扛不住这种泄漏。
- 必须自己构造
*http.Client,设Timeout: 8 * time.Second(阿里云/互亿无线文档明确建议 5–10 秒) - 别漏
Transport的MaxIdleConns和MaxIdleConnsPerHost,高并发下连接池耗尽会导致dial tcp: lookup xxx: no such host - HTTP 状态码
200不代表短信发成功——它只表示请求被接收;真正结果在响应体里,比如互亿无线返回{"code":2,"msg":"提交成功"}才算过第一关
签名计算必须严格按文档顺序拼接
“Signature not match” 是最常卡住的点,问题几乎从不在哈希算法本身,而在参与签名的参数没按字典序排列、URL 编码层级不对、或时间戳用了 13 位 Unix 毫秒而非 10 位秒。
初始化并管理阿里云SDK Go 客户端,涵盖 sync.Once 单例、goroutine 安全、endpoint 与 region 配置、VPC 端点及调试。
- 互亿无线要求:签名原文 =
account + password + mobile + content + time,再 MD5;其中time是strconv.FormatInt(time.Now().Unix(), 10) - 阿里云要求:所有请求参数(含
AccessKeyId、SignatureMethod、Timestamp等)按字典序升序排列,url.QueryEscape编码 value,再拼成key1=value1&key2=value2字符串,最后 HMAC-SHA256 - 注意:
url.PathEscape和url.QueryEscape行为不同——前者不转义&和=,后者才适合 query 参数值;混用必错
手机号、模板、内容格式不能凭经验写
看似简单的字段,错一个字符就直接拒收。运营商和平台对格式校验极严。
- 手机号必须是纯数字 11 位(中国大陆),不能带
+、0086、空格或横线;+8613912345678在阿里云可接受,但在互亿无线会返回code=4071(号码格式错误) - 互亿无线调试期只能用默认模板:
您的验证码是:【变量】。请不要把验证码泄露给其他人。;变量必须是纯数字 4–6 位,不能含字母或符号 - 阿里云必须用已审核通过的
TemplateCode,且TemplateParam是 JSON 字符串,如`{"code":"837291"}`;键名必须和模板里定义的完全一致,大小写敏感
响应解析要分层判断,不能只看 HTTP 状态码
服务商返回 200 是常态,但 body 里可能是 {"code":405,"msg":"API ID 错误"}。不解析 body,等于没做校验。
- 先检查
resp.StatusCode是否在200–299范围;不是就直接报网络/HTTP 层错误(如 401、415、502) - 再
json.Unmarshal响应体,看业务字段:code == 2(互亿无线)或response.Code == "OK"(阿里云)才算成功 - 特别注意:互亿无线的
code=4085表示单日发送超限(通常 10 条),不是配置错——得加 Redis 限流,按手机号 + 时间窗口计数
真正难的不是写几行 HTTP 请求,而是把每个平台文档里藏在角落的约束条件抠出来,一条条对齐。比如互亿无线的 password 字段在签名时要用明文拼接,而阿里云的 Signature 是基于整个请求字符串生成的——这两个逻辑一旦写反,调试三天也看不出哪错了。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










