etcd是分布式强一致KV存储系统。
关于etcd的介绍和使用,可以查阅上篇文章etcd入门。
本文主要介绍在golang中是如何使用etcd的。
安装package
etcd 官方提供了golang语言的client package go.etcd.io/etcd/clientv3
。这里介绍的v3版本的使用。
下载已经发布版本的source code。
例如,v3.4.13 ,下载地址v3.4.13。
下载后,解压到$GOPATH目录下:
tar zvxf etcd-3.4.13.tar.gz -C /home/lanyang/workspace/go_projects/src/go.etcd.io/
cd /home/lanyang/workspace/go_projects/src/go.etcd.io/
mv etcd-3.4.13/ etcd
如果直接使用go get go.etcd.io/etcd/clientv3
,会直接下载最新的代码,可能没有经过严格测试,出现类似
cannot use &errPicker literal (type *errPicker) as type Picker in return argument 这样的错误。
使用
下面代码中,先初始化连接配置,接着put一个值,最后get查看结果。
package main
import (
"context"
"log"
"time"
"go.etcd.io/etcd/clientv3"
)
func main() {
cli, err := clientv3.New(clientv3.Config{
Endpoints: []string{"localhost:2379", "localhost:2479", "localhost:2579"},
DialTimeout: 5 * time.Second,
})
if err != nil {
log.Println("connect to etcd failed, err:", err)
return
}
defer cli.Close()
ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
putResp, err := cli.Put(ctx, "fruit", "orange")
cancel()
if err != nil {
log.Println("put to ectcd failed:", err)
return
}
log.Println("putResp:", putResp)
ctx, cancel = context.WithTimeout(context.Background(), 1*time.Second)
getResp, err := cli.Get(ctx, "fruit")
cancel()
if err != nil {
log.Printf("get from etcd failed, err:%v
", err)
return
}
log.Println("getResp:", getResp)
for _, ev := range getResp.Kvs {
log.Printf("%s:%s
", ev.Key, ev.Value)
}
}
启动etcd服务(具体安装可见etcd 入门),接着执行上面的代码。
输出结果:
2020-10-18 12:45:28.370946 I | putResp: &{cluster_id:3868734316268835716 member_id:2759271418354571410 revision:7 raft_term:31 <nil>}
2020-10-18 12:45:28.373794 I | getResp: &{cluster_id:3868734316268835716 member_id:2759271418354571410 revision:7 raft_term:31 [key:"fruit" create_revision:7 mod_revision:7 version:1 value:"orange" ] false 1}
2020-10-18 12:45:28.373810 I | fruit:orange
PUT
GET
返回错误类型主要由两种,一种是context error,cancel的和context deadline。
另一种是,gRPC error。
可以定义一个handler专门处理错误:
func errHandler(err error) {
switch err {
case context.Canceled:
log.Fatalf("ctx is canceled by another routine: %v", err)
case context.DeadlineExceeded:
log.Fatalf("ctx is attached with a deadline is exceeded: %v", err)
case rpctypes.ErrEmptyKey:
log.Fatalf("client-side error: %v", err)
default:
log.Fatalf("bad cluster endpoints, which are not etcd servers: %v", err)
}
}