用 net/http 直接发 POST 请求最可控,因其轻量、无依赖、便于调试,且可精准控制 Content-Type、Authorization、JSON 请求体等关键点。
用
直接发 POST 请求最可控
OpenAI 的 Chat Completions API 本质就是个 REST 接口,
足够轻量、无依赖、便于调试。很多项目盲目上
,结果卡在 token 刷新、流式响应解析或自定义 header 上——其实多数需求只需要发一次 JSON 请求并读回
。
关键点:
必须设为
,漏掉会返回
header 格式是
,注意开头有空格
请求体必须是合法 JSON,
字段不能拼错(比如写成
)
Go 默认不自动解 gzip,但 OpenAI 响应通常未压缩,不用额外处理
示例片段:
用
库时要注意
初始化和超时
这个库封装得不错,但默认没设超时,生产环境容易卡死;而且它把 API key 写死在
实例里,没法动态切换 key 或做租户隔离。
立即学习
“
go语言免费学习笔记(深入)
”;
实操建议:
go语言参考手册 中文CHM版
Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。本文给大家带来Go参考手册,需要的可以来下载! Go是从2007年末由Robert Griesemer, Rob Pike, Ken Thompson主持开发,后来还加入了Ian Lance Taylor, Russ Cox等人,并最终于2009年11月开源,在2012年早些时候发布了Go 1稳定版本。现在Go的开发已经是完全开放的,并且拥有一个活跃的社区。 Go 语言特色 简洁、快速、安全 并行、有趣、开源 内存管理、v数组安全、编译
下载
初始化时显式传入
,自己控制
和
不要复用全局
实例来服务不同用户,key 是实例级的
流式调用(
)需手动 close
,否则 goroutine 泄漏
错误类型不是标准
,要检查
字段,而不是只看
遇到
不能只靠重试
OpenAI 的限流是按「每分钟请求数」和「每分钟 token 数」双重计算的,单纯 sleep + retry 容易失败。尤其当多个 goroutine 并发调用时,本地重试可能让问题更糟。
更稳的做法:
在请求前加简单令牌桶(如
),限制每秒最大请求数
从响应 header 里读
和
,动态调整等待时间
对高频小请求(如批量打标),合并成单次
数组,比串行调用省 token 也少触发限流
别在
http.Transport 上调大
,OpenAI 不支持长连接复用,反而占着 fd
中文输出乱码或截断?检查
和 UTF-8 编码
Go 的
默认按 UTF-8 解析,但如果你用
读响应体后又手动转
,再塞进结构体,中间若误用了
截断或错误切片,会导致中文变
或提前终止。
安全做法:
直接对响应 body 做
,别中间转 string
如果需要日志记录原始响应,用
,别用
随意截
结构体字段用
接收不确定格式的字段(比如函数调用返回的
),避免因字段缺失 panic
响应中
字段值本身就是字符串,不需要额外
或
真正容易被忽略的是:OpenAI 返回的 JSON 本身是严格 UTF-8,但你的终端、IDE 或日志系统如果没设 UTF-8 编码,看起来就是乱码——先确认是传输层问题,还是显示层问题。
net/httpnet/httpgithub.com/sashabaranov/go-openaichoices[0].message.contentContent-Typeapplication/json400 Bad RequestAuthorizationBearer sk-xxxmodelmodlereqBody := map[string]interface{}{
"model": "gpt-3.5-turbo",
"messages": []map[string]string{
{"role": "user", "content": "你好"},
},
}
data, _ := json.Marshal(reqBody)
resp, _ := http.Post("https://api.openai.com/v1/chat/completions", "application/json", bytes.NewBuffer(data))
go-openaiClientClienthttp.ClientTimeoutTransportopenai.ClientCreateChatCompletionStreamresponseerrorresp.Error.Messageerr != nil429 Too Many Requestsgolang.org/x/time/rate.LimiterX-RateLimit-RemainingX-RateLimit-ResetmessagesdefaultMaxIdleConnsjson.RawMessagejson.Unmarshalio.ReadAllstring()[]bytejson.Unmarshalfmt.Printf("%s", body)string(body[:n])json.RawMessagefunction_callcontenturl.QueryUnescapebase64.StdEncoding.DecodeString