Go语言对etcd的基本操作
本文简单介绍Go语言对etcd v3的基本操作。
1. Import package
1 2 3 4 | import ( "github.com/coreos/etcd/clientv3" "github.com/coreos/etcd/mvcc/mvccpb" ) |
2. Declare Variables
1 2 3 4 5 6 7 8 9 10 11 | var cli *clientv3.Client var serverList = []string{ "192.168.3.102:2379" , "192.168.3.105:2379" , "192.168.3.103:2379" , } var userName = "root" var password = "shiajun666" var dialTimeout = 5 var opTimeout = 5 |
3. Connect to etcd server
1 2 3 4 5 6 7 8 9 10 11 | var err error cli, err := clientv3.New(clientv3.Config{ Endpoints: serverList, DialTimeout: time.Duration(dialTimeout) * time.Second, Username: userName, Password: password, }) if err != nil { fmt.Println( "Connect etcd server failed: " , err) return } |
4. Get
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() key := "name" resp, err := cli.Get(ctx, key) if err != nil { fmt.Printf( "Get key[%s] failed: %v\n" , key, err) return } if len(resp.Kvs) == 0 { fmt.Printf( "Key[%s] not exists.\n" , key) return } fmt.Println( "value: " , string(resp.Kvs[0].Value)) |
Get 方法的返回值如下:

其中 Header *ResponseHeader 几乎是etcd所有方法返回值中都会包含的,它包含了集群ID、etcd节点成员ID、key全局版本号、raft任期号:

Kvs []*mvccpb.KeyValue 包含多个键值对的信息,几乎etcd所有方法返回的键值对信息都由 mvccpb.KeyValue 表示,其结构如下:

5. Get values according to key prefix
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() prefix := "name" resp, err := cli.Get(ctx, prefix, clientv3.WithPrefix()) if err != nil { fmt.Printf( "Get key prefix[%s] failed: %v\n" , prefix, err) return } if len(resp.Kvs) == 0 { fmt.Printf( "Key prefix[%s] not exists.\n" , prefix) return } fmt.Println( "values: " , resp.Kvs) |
6. put
1 2 3 4 5 6 7 8 9 10 11 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() key := "name" value := "shiajun" _, err = cli.Put(ctx, key, value) if err != nil { fmt.Printf( "Put key[%s] value[%s] failed: %v\n" , key, value, err) return } fmt.Println( "put success" ) |
Put 方法返回值如下:

prevKv 表示当前Put操作执行之前该key的键值对信息,Put方法第四个参数加上 clientv3.WithPrevKV() 即可返回该信息,如下一个例子所示。
7. put new value and get prev value
1 2 3 4 5 6 7 8 9 10 11 12 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() key := "name" value := "shiajun" opts := []clientv3.OpOption{clientv3.WithPrevKV()} resp, err := cli.Put(ctx, key, value, opts...) if err != nil { fmt.Printf( "Put key[%s] value[%s] failed: %v\n" , key, value, err) return } fmt.Println( "prev value: " , string(resp.PrevKv.Value)) |
8. put with lease
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() //grant lease var ttl int64 = 10 lease, err := cli.Grant(ctx, ttl) if err != nil { fmt.Printf( "Grant lease failed: %v\n" , err) } //put with lease key := "name" value := "shiajun" _, err = cli.Put(ctx, key, value, clientv3.WithLease(lease.ID)) if err != nil { fmt.Printf( "Put key[%s] value[%s] with lease[%s] failed: %v\n" , key, value, lease.ID, err) } fmt.Println( "put with lease success" ) |
Grant 方法返回值如下:

9. put with lease and keep alive
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() //grant lease var ttl int64 = 10 lease, err := cli.Grant(ctx, ttl) if err != nil { fmt.Printf( "Grant lease failed: %v\n" , err) } //put with lease key := "name" value := "shiajun" _, err = cli.Put(ctx, key, value, clientv3.WithLease(lease.ID)) if err != nil { fmt.Printf( "Put key[%s] value[%s] with lease[%s] failed: %v\n" , key, value, lease.ID, err) } //keep alive kaCh, err := cli.KeepAlive(context.Background(), lease.ID) if err != nil { fmt.Printf( "Keep alive key[%s] value[%s] with lease[%s] failed: %v\n" , key, value, lease.ID, err) } for { kaResp := <-kaCh fmt.Println( "ttl: " , kaResp.TTL) } |
KeepAlive 方法返回值为一个channel:<-chan *LeaseKeepAliveResponse,接收每一次 keep alive 的结果返回:

10. delete
1 2 3 4 5 6 7 8 9 10 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() key := "name" _, err = cli.Delete(ctx, key) if err != nil { fmt.Printf( "Delete key[%s] failed: %v\n" , key, err) return } fmt.Println( "delete success" ) |
Delete 方法返回值如下:

11. watch
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | key := "name" opts := []clientv3.OpOption{clientv3.WithPrevKV(), clientv3.WithPrefix()} wCh := cli.Watch(context.Background(), key, opts...) for resp := range wCh { for _, event := range resp.Events { if event.Type == mvccpb.PUT { fmt.Println( "put happens" ) } else if event.Type == mvccpb.DELETE { fmt.Println( "delete happens" ) } fmt.Println( "prev value: " , event.PrevKv) fmt.Println( "value: " , event.Kv) } } |
Watch 方法返回值为一个Channel:<-chan WatchResponse,接收watch的结果信息:

对watch的key进行put、delete操作,watch操作即可获得变更结果,示例如下:

12. compare and set - transation
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ctx, cancel := context.WithTimeout(context.Background(), time.Duration(opTimeout)*time.Second) defer cancel() key := "number" kvc := clientv3.NewKV(cli) resp, err := kvc.Txn(ctx). If(clientv3.Compare(clientv3.Value(key), ">" , "0" )). Then(clientv3.OpPut(key, "100" )). Else(clientv3.OpPut(key, "99" )). Commit() if err != nil { fmt.Errorf( "Compare and set transation failed: %v\n" , err) } fmt.Println(resp.Succeeded) |
这是使用etcd事务实现的一个先比较再赋值的简单例子:若 number 的值大于0,则将number赋值为100,否则赋值为99。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· AI与.NET技术实操系列(五):向量存储与相似性搜索在 .NET 中的实现
· 超详细:普通电脑也行Windows部署deepseek R1训练数据并当服务器共享给他人
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)