gocb.Connect() 应传纯节点地址列表(如"10.0.1.5","10.0.1.6"),不带协议头,不走8091端口;必须显式提供用户名密码,启用TLS需手动配置TLSConfig,Bucket须预先创建并配对应权限。

gocb.Connect() 传什么地址才对
直接填 couchbase://127.0.0.1 或 http://localhost:8091 肯定连不上——gocb.Connect() 接收的是纯节点地址列表,不带协议头,也不走 HTTP 端口。它默认用二进制协议连 11210 端口(不是管理端口 8091)。
正确写法是只传 IP 或域名,多个用逗号分隔:
cluster, err := gocb.Connect("10.0.1.5", "10.0.1.6", gocb.ClusterOptions{
Username: "Administrator",
Password: "password",
})
- 单节点开发也必须显式传
Username/Password,哪怕控制台里没开鉴权;否则后续打开 Bucket 会静默失败 - 如果集群启用了 TLS(比如 Capella 或自建集群配了证书),必须手动传
TLSConfig,否则连接超时无报错 - 地址里出现
couchbase://会导致解析失败或降级为 DNS SRV 查找,结果连错节点甚至连不上
Bucket 必须提前建好,且权限要配对
cluster.Bucket("my-bucket") 不创建 Bucket,只是获取句柄;如果名字不存在或当前用户没权限,bucket.DefaultCollection() 才会报错——常见错误是 gocb.ErrBucketNotFound 或看似无关的 gocb.ErrAuthenticationFailure(其实是权限不足)。
- Bucket 必须在 Web 控制台或 CLI 中预先创建,不能运行时生成
- 用户至少要有该 Bucket 的 Application Access 权限,别直接给 Admin 角色
- 4.5+ 版本默认启用 Collections,优先用
bucket.DefaultCollection(),别再用已弃用的bucket.Get() - 如果 Bucket 内存配额已满,
Upsert()会返回gocb.ErrTemporaryFailure,不是代码问题,得调大配额或清理旧数据
写文档优先用 Upsert(),不是 Insert()
Insert() 要求 ID 绝对不能存在,否则崩出 gocb.ErrDocumentExists;而 Upsert() 无论 ID 是否存在都成功——覆盖或新建,这才是业务逻辑的真实需求。
立即学习“go语言免费学习笔记(深入)”;
比如更新用户资料、刷新订单状态、写缓存,都应该用:
_, err := collection.Upsert("user::123", map[string]interface{}{
"name": "Alice",
"updated_at": time.Now().Unix(),
}, nil)
- 除非你明确需要“仅当文档不存在时才写入”(如注册唯一 ID),否则别用
Insert() -
Upsert()第三个参数是*gocb.UpsertOptions,可设过期时间(Expiry)、CAS 值等,按需传 - 写完不检查
err是最大隐患:网络抖动、权限变更、配额满都会在这里失败,必须判错
读文档后必须手动解析 JSON 并检查 err
collection.Get() 返回的是 *gocb.GetResult,内容在 Content() 方法里,但这个方法本身可能出错;而且返回值是 interface{},得自己反序列化。
res, err := collection.Get("user::123", nil)
if err != nil {
// 这里处理 not found、timeout、权限等错误
}
var data map[string]interface{}
err = res.Content(&data) // 这一步也可能 err!比如字段类型不匹配
if err != nil {
// 处理 JSON 解析失败
}
-
res.Content()是易被忽略的第二道错误点,不能只判Get()的 err - 如果文档结构固定,建议定义 struct 并传指针进去,比
map[string]interface{}更安全 - 没设 TTL 的文档不会自动过期,长期堆积会撑爆内存配额,读之前最好确认业务是否需要设置
Expiry
err 类型,比猜更快。


















