必须通过https://aip.baidubce.com/oauth/2.0/token发起GET请求,传入grant_type=client_credentials、client_id(API Key)和client_secret(Secret Key),从JSON响应中提取access_token,并用sync.Map缓存+过期时间戳实现自动刷新,避免重复获取或过期失效。

能调,但必须自己拼 HTTP 请求,官方没有 Go SDK。直接用 net/http 或 go-resty 就行,关键在 token 获取、请求构造和流式响应处理这三步,漏一个就卡住。
如何正确获取并刷新 access_token
文心 API 不接受原始 API_KEY/SECRET_KEY,所有请求必须带有效的 access_token,且有效期只有 30 分钟。不能写死,也不能每次请求都重新拿。
-
access_token必须通过https://aip.baidubce.com/oauth/2.0/token发起 GET 请求获取,参数是grant_type=client_credentials、client_id(即API_KEY)、client_secret(即SECRET_KEY) - 响应是 JSON,用
gjson.Get(resp, "access_token").String()或json.Unmarshal提取,空值要报错退出 - 别在每次 API 调用前都请求 token——加个内存缓存(比如用
sync.Map存 token + 过期时间戳),调用前先检查是否剩余 > 60 秒;快过期时用 goroutine 异步刷新,避免阻塞主流程
chat/completions 和 chat/eb-instant 两个 endpoint 怎么选
前者是通用 chat 接口(对应 ERNIE-Bot-4 等模型),后者是 turbo 专用流式接口(ERNIE-Bot-turbo)。不是所有模型都支持后者,选错会返回 404 或 model not found。
-
/chat/completions:适用于非流式、需要完整响应再处理的场景,请求体里stream: false(默认),响应结构固定,choices[0].message.content是答案 -
/chat/eb-instant:仅 turbo 模型可用,必须设stream: true,响应是 SSE 格式,每行以data:开头,需手动按行解析、跳过空行和event:行,最后合并delta.content - URL 中的 model 名称不参与 path,而是放在请求体
model字段里(如"ernie-bot-turbo"),但/eb-instant实际忽略该字段,只认 turbo
流式响应解析容易崩在哪儿
Go 默认的 http.Response.Body 是 io.ReadCloser,但 SSE 流不能直接 json.Unmarshal 整体读——会卡死或丢数据。必须边读边 parse,且要容忍服务端偶尔发来的空行、注释行(: ping)。
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
立即学习“go语言免费学习笔记(深入)”;
- 用
bufio.Scanner按行扫,scanner.Split(bufio.ScanLines),每行 trim 后判断是否以data:开头 - 遇到
data: [DONE]就终止循环;遇到data: {"delta":{"content":"..."}}才解析 JSON,提取delta.content并追加到结果字符串 - 别用
ioutil.ReadAll或io.ReadAll试图一次性读完——流没结束前会一直 block,超时或 context cancel 后连接可能已断,但 goroutine 还卡在读 - 务必设置
http.Client.Timeout和context.WithTimeout,否则网络抖动时 goroutine 泄露风险极高
并发调用时 token 和 client 复用要注意什么
token 是全局共享的,但 http.Client 可以复用,http.Transport 的连接池能显著降低 TLS 握手开销。不过百度 API 有 QPS 限制(千帆后台可查配额),硬并发上去只会触发 429 Too Many Requests。
-
http.Client应定义为包级变量,复用底层 TCP 连接;Transport.MaxIdleConns和MaxIdleConnsPerHost建议设为 100+,避免频繁建连 - 不要为每个请求 new 一个
http.Client,否则 fd 耗尽、TLS 缓存失效、DNS 缓存丢失全来一遍 - 真实业务中建议加一层限流:用
golang.org/x/time/rate.Limiter控制每秒请求数,比靠 429 重试更可控 - token 刷新过程要加
sync.Once或sync.RWMutex,防止多个 goroutine 同时发起 token 请求,造成配额浪费或响应冲突
token 有效期短、流式协议不标准、错误码含义模糊(比如 500 可能是鉴权失败也可能是模型内部错误),这些地方不提前兜底,上线后第一波流量就会暴露问题。

















