diff --git a/.gitignore b/.gitignore index 24ebcf5..5d4ba0b 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ dump.rdb + +.idea \ No newline at end of file diff --git a/redis.go b/redis.go index 0987e18..d7a48e6 100644 --- a/redis.go +++ b/redis.go @@ -121,6 +121,8 @@ type Item struct { ZSetValues map[string]float64 + HashValues map[string]string + // Flags 一些 redis 标记位,请参考 Flag 开头的常量定义 Flags uint32 @@ -810,3 +812,87 @@ func (c *Client) SMembers(ctx context.Context, key string) (items [][]byte, err }) return } + +// Hashes +func (c *Client) HSet(ctx context.Context, key string, hashes map[string]string) (added int64, err error) { + args := []interface{}{"hset", key} + + for f, v := range hashes { + args = append(args, f) + args = append(args, v) + } + + err = c.do(ctx, args, func(conn *redisConn) error { + if err := conn.w.WriteArgs(args); err != nil { + return err + } + + if err := conn.w.Flush(); err != nil { + return err + } + + added, err = conn.r.ReadIntReply() + if err != nil { + return err + } + return nil + }) + return +} + +func (c *Client) HGet(ctx context.Context, key string, field string) (item *Item, err error) { + args := []interface{}{"hget", key, field} + err = c.do(ctx, args, func(conn *redisConn) error { + if err := conn.w.WriteArgs(args); err != nil { + return err + } + + if err := conn.w.Flush(); err != nil { + return err + } + + var b []byte + if b, err = conn.r.ReadBytesReply(); err != nil { + item = nil + return err + } + + item = &Item{Value: b} + + return nil + }) + return +} + +func (c *Client) HGetAll(ctx context.Context, key string) (item *Item, err error) { + args := []interface{}{"hgetall", key} + err = c.do(ctx, args, func(conn *redisConn) error { + if err := conn.w.WriteArgs(args); err != nil { + return err + } + + if err := conn.w.Flush(); err != nil { + return err + } + + l, err := conn.r.ReadArrayLenReply() + if err != nil { + return err + } + hashes := make(map[string] string, l / 2) + for i := 0; i < l; i += 2 { + field, err := conn.r.ReadBytesReply() + if err != nil { + return err + } + value, err := conn.r.ReadBytesReply() + if err != nil { + return err + } + hashes[string(field)] = string(value) + } + item = &Item{HashValues: hashes} + return nil + }) + return +} diff --git a/redis_test.go b/redis_test.go index 5013127..ad313ed 100644 --- a/redis_test.go +++ b/redis_test.go @@ -354,3 +354,34 @@ func TestSet(t *testing.T) { t.Logf("Key: foo, SRem: %d; Failed, err: %v", result, err) } } + +func TestHash(t *testing.T) { + c := New(Options{ + Address: os.Getenv("REDIS_HOST"), + PoolSize: 1, + }) + + testKey := "hashtest" + + if err := c.Del(ctx, testKey); err != nil { + t.Fatal("start faild") + } + + // hset + added, _ := c.HSet(ctx, testKey, map[string]string{"name": "bilibili", "age": "20"}) + if added != 2 { + t.Fatalf("hset %s failed", testKey) + } + // hget + item, _ := c.HGet(ctx, testKey, "name") + if !bytes.Equal(item.Value, []byte("bilibili")) { + t.Fatalf("hget %s failed", testKey) + } + + // hgetall + hgetallItem, _ := c.HGetAll(ctx, testKey) + for f, v := range hgetallItem.HashValues { + t.Logf("Key: %s, field: %s, value: %s", testKey, f, v) + } + +}