kvdb 是 EdgeOne CLI 内置 kv-client 的 Go 语言移植版,提供完整的控制面与数据面链路支持,可作为生产级 Go SDK 嵌入各类服务。
两条主要链路:
package main
import (
"context"
"log"
"time"
kv "cnb.cool/svn/kv"
)
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
// 1. 直接打开单个 KV client
client, err := kv.OpenGlobalClient(
ctx,
"YOUR_API_TOKEN",
kv.WithPlaneProjectID("pages-xxxx"),
kv.WithPlaneBindingName("kvdb"),
kv.WithPlaneClientOptions(
kv.WithConnectTimeout(10 * time.Second),
kv.WithCommandTimeout(10 * time.Second),
),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
// 2. 读写数据
if err := client.PutString(ctx, "hello", "world"); err != nil {
log.Fatal(err)
}
value, found, err := client.GetString(ctx, "hello")
if err != nil {
log.Fatal(err)
}
if found {
log.Println("hello =", value)
}
}
适用于 EdgeOne Pages 部署环境,绑定信息通过 EO_KV_BINDINGS 环境变量自动注入:
package main
import (
"context"
"log"
"time"
kv "cnb.cool/svn/kv"
)
func main() {
// 从 EO_KV_BINDINGS 环境变量加载注册表
registry, ok, err := kv.LoadRegistryFromEnv()
if err != nil {
log.Fatal(err)
}
if !ok {
log.Fatal("EO_KV_BINDINGS 环境变量未设置")
}
defer registry.Close()
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
client, err := registry.Client("kvdb")
if err != nil {
log.Fatal(err)
}
value, found, err := client.GetString(ctx, "hello")
// ...
}
go get cnb.cool/svn/kv@latest
git clone https://cnb.cool/svn/kv
cd kv
go test ./...
模块信息:
cnb.cool/svn/kvkv| 方法 | 说明 |
|---|---|
OpenGlobalClient(ctx, token, opts...) | 直接通过国际站打开单个 KV client |
OpenChinaClient(ctx, token, opts...) | 直接通过中国站打开单个 KV client |
NewChinaPlaneClient(token, opts...) | 创建默认指向中国站的控制面客户端 |
NewGlobalPlaneClient(token, opts...) | 创建默认指向国际站的控制面客户端 |
NewPlaneClient(region, token, opts...) | 创建控制面客户端 |
(*PlaneClient).FetchBindings(ctx, projectID...) | 拉取项目的 KV 绑定列表;若已配置默认 ProjectId,可省略参数 |
(*PlaneClient).ResolveBinding(ctx, selector) | 在默认项目内解析单个绑定 |
(*PlaneClient).OpenClient(ctx, selector, opts...) | 直接打开单个 KV client |
(*PlaneClient).ListProjects(ctx) | 枚举可见的 Pages 项目 |
(*PlaneClient).FindProjectByNamespace(ctx, namespace) | 通过绑定名/namespace 反推项目信息 |
(*PlaneClient).InferProjectIDByNamespace(ctx, namespace) | 通过绑定名/namespace 反推 ProjectID |
DecryptBindings(encrypted) | 解密控制面返回的加密绑定数据 |
| 方法 | 说明 |
|---|---|
NewClient(binding, opts...) | 创建数据面客户端 |
(*Client).Get(ctx, key) | 读取键值,返回 []byte |
(*Client).GetString(ctx, key) | 读取键值,返回 string |
(*Client).GetJSON(ctx, key, target) | 读取并反序列化 JSON |
(*Client).Put(ctx, key, value) | 写入原始字节 |
(*Client).PutString(ctx, key, value) | 写入字符串 |
(*Client).PutJSON(ctx, key, value) | 序列化并写入 JSON |
(*Client).Delete(ctx, key) | 删除键 |
(*Client).List(ctx, opts) | 按前缀列举键(支持分页) |
(*Client).Close() | 关闭客户端,释放连接 |
(*Client).Binding() | 获取当前绑定的配置副本 |
| 方法 | 说明 |
|---|---|
NewRegistry(bindings, opts...) | 从绑定列表创建注册表 |
(*Registry).Names() | 获取所有已注册绑定名(排序) |
(*Registry).Binding(name) | 获取指定绑定的配置 |
(*Registry).Client(name) | 获取指定绑定的客户端(懒创建) |
(*Registry).Close() | 关闭注册表内所有客户端 |
| 函数 | 说明 |
|---|---|
LoadRegistryFromEnv(opts...) | 从 EO_KV_BINDINGS 加载注册表 |
ConsumeRegistryFromEnv(opts...) | 加载并清除环境变量 |
FetchRegistry(ctx, region, token, projectID, cpOpts, clientOpts...) | 通过控制面拉取并创建注册表 |
// 设置建连超时(默认 10s)
kv.WithConnectTimeout(15 * time.Second)
// 设置单条命令超时(默认 10s)
kv.WithCommandTimeout(15 * time.Second)
// 注入日志器(用于调试)
kv.WithLogger(customLogger)
// 覆盖默认 API 地址
kv.WithPlaneBaseURL("https://custom-api.example.com")
// 注入自定义 HTTP 客户端
kv.WithPlaneHTTPClient(customHTTPClient)
// 预设默认 ProjectId;之后可直接 client.FetchBindings(ctx)
kv.WithPlaneProjectID("pages-xxxx")
// 预设默认 BindingName;之后可直接 client.OpenClient(ctx, "")
kv.WithPlaneBindingName("kvdb")
// 手动覆盖地域(优先级高于 NewPlaneClient 第一个参数)
kv.WithPlaneRegion(kv.RegionGlobal)
// 设置默认 HTTP 超时
kv.WithPlaneTimeout(20 * time.Second)
// 设置自定义 User-Agent
kv.WithPlaneUserAgent("my-app/1.0")
// 调整项目枚举分页大小(用于 ProjectId 反推)
kv.WithPlaneProjectPageSize(200)
// 为高阶入口预设数据面 Client 参数
kv.WithPlaneClientOptions(
kv.WithConnectTimeout(10 * time.Second),
kv.WithCommandTimeout(10 * time.Second),
)
推荐写法:
client, err := kv.OpenGlobalClient(
ctx,
"YOUR_API_TOKEN",
kv.WithPlaneProjectID("pages-xxxx"),
kv.WithPlaneBindingName("kvdb"),
kv.WithPlaneClientOptions(
kv.WithConnectTimeout(10 * time.Second),
kv.WithCommandTimeout(10 * time.Second),
),
)
if err != nil {
log.Fatal(err)
}
defer client.Close()
若你的主环境在中国站,则对应写法是:
client, err := kv.OpenChinaClient(
ctx,
"YOUR_API_TOKEN",
kv.WithPlaneProjectID("pages-xxxx"),
kv.WithPlaneBindingName("kvdb"),
)
如果你还想保留控制面对象本身,再使用:
planeClient, err := kv.NewGlobalPlaneClient(
"YOUR_API_TOKEN",
kv.WithPlaneProjectID("pages-xxxx"),
kv.WithPlaneBindingName("kvdb"),
)
if err != nil {
log.Fatal(err)
}
client, err := planeClient.OpenClient(ctx, "")
cd kv
go test ./...
go test -race ./...
export EDGEONE_KV_E2E=1
export EDGEONE_KV_API_TOKEN='YOUR_TOKEN'
export EDGEONE_KV_REGION='global'
export EDGEONE_KV_PROJECT_ID='pages-xxxx'
export EDGEONE_KV_BINDING_NAME='kvdb'
go test -run TestE2EEdgeOne -v
端到端测试会自动执行:
| 文档 | 说明 |
|---|---|
| README.md | 项目说明与快速开始(本文档) |
| MANUAL.md | 完整使用手册 |
| DESIGN.md | 架构设计与实现细节 |
cnb.cool/svn/kvcmd/kvdb-cli/main.gohttps://pages-api.edgeone.ai/v1https://pages-api.cloud.tencent.com/v1