可以看到通过客户端方法Do/Receive获取的数据都是二进制形式[]byte的,需要开发者手动进行数据转换。

当然,gredis模块也提供了DoVar/ReceiveVar方法,用以获取可供方便转换的gvar.Var通用变量结果。通过gvar.Var的强大转换功能可以转换为任意的数据类型,如基本数据类型Int,String,Strings,或者结构体Struct等等。

DoVar示例

package main

import (
    "fmt"
    "github.com/gogf/gf/frame/g"
)

func main() {
    conn := g.Redis().Conn()
    defer conn.Close()
    conn.Do("SET", "k", "v")
    v, _ := conn.DoVar("GET", "k")
    fmt.Println(v.String())
}

执行后,输出结果为:

v

ReceiveVar示例

package main

import (
	"fmt"
	"github.com/gogf/gf/frame/g"
)

func main() {
	conn := g.Redis().Conn()
	defer conn.Close()
	_, err := conn.Do("SUBSCRIBE", "channel")
	if err != nil {
		panic(err)
	}
	for {
		reply, err := conn.ReceiveVar()
		if err != nil {
			panic(err)
		}
		fmt.Println(reply.Strings())
	}
}

执行后,程序将阻塞等待获取数据。

另外打开一个终端通过redis-cli命令进入Redis Server,发布一条消息:

$ redis-cli
127.0.0.1:6379> publish channel test
(integer) 1
127.0.0.1:6379>

随后程序终端立即打印出从Redis Server获取的数据:

[message channel test]

HashSet示例

HashSet是我们比较常用的Redis数据结构,我们可以非常方便地将Redis中的HashSet获取并转换为Golang Map

package main

import (
	"fmt"
	"github.com/gogf/gf/container/gvar"
	"github.com/gogf/gf/frame/g"
)

func main() {
	var (
		err    error
		result *gvar.Var
		key    = "user"
	)
	_, err = g.Redis().Do("HSET", key, "id", 10000)
	if err != nil {
		panic(err)
	}
	_, err = g.Redis().Do("HSET", key, "name", "john")
	if err != nil {
		panic(err)
	}
	result, err = g.Redis().DoVar("HGETALL", key)
	if err != nil {
		panic(err)
	}
	fmt.Println(result.Map())

	// May Output:
	// map[id:10000 name:john]
}
Content Menu

  • No labels

12 Comments

  1. `HashSet是我们比较常用的Redis数据结构` ??

  2. 为什么经过DoVar出来的结果会被base64编码

     var (
    	config = gredis.Config{
    		Host: "127.0.0.1",
    		Port: 6379,
    		Db:   0,
    	}
    ) 
    func main() {  
    	group := "test"
    	gredis.SetConfig(&config, group)
    
    	redis := gredis.Instance(group)
    	defer redis.Close()
    
    	_, err := redis.Do("ZADD", "mykey", 1, "golang", 2, "c++", 3, "java")
    	if err != nil {
    		panic(err)
    	}
    	r, err := redis.Do("ZSCAN", "mykey", 0)
    	if err != nil {
    		panic(err)
    	}
    
    	if list, ok := r.([]interface{}); ok {
    		fmt.Println(len(list), list)
    		if len(list) >= 2 {
    			fmt.Println(gconv.String(list[0]))
    			fmt.Println(gconv.Strings(list[1]))
    		}
    	}
    	fmt.Println("----------------------------")
    	r1, err := redis.DoVar("ZSCAN", "mykey", 1)
    	if err != nil {
    		panic(err)
    	}
    	fmt.Println(r1)
    }
    2 [[48] [[103 111 108 97 110 103] [49] [99 43 43] [50] [106 97 118 97] [51]]]
    0
    [golang 1 c++ 2 java 3]
    ----------------------------
    ["0","[\"Z29sYW5n\",\"MQ==\",\"Yysr\",\"Mg==\",\"amF2YQ==\",\"Mw==\"]"]
    
    
    1. 因为底层数据是[]byte类型,打印出来的时候fmt包会按照base64打印。

      1. 并不是,是转换底层调用了json.Marshal

        C:\hailaz\go\pkg\mod\github.com\gogf\gf@v1.15.7\util\gconv\gconv.go:420

        C:\Program Files\Go\src\encoding\json\encode.go

        // Array and slice values encode as JSON arrays, except that
        // []byte encodes as a base64-encoded string, and a nil slice
        // encodes as the null JSON value.

        1. 为什么经过DoVar出来的结果会被base64编码?

          回答:因为底层数据是[]byte类型,打印出来的时候fmt包会按照base64打印。

          1. 这跟fmt真的没关系

            	bs := []byte{48, 49}
            	fmt.Println(bs, string(bs))
            	b, _ := json.Marshal(bs)
            	fmt.Println(b, string(b))
            
            // output
            [48 49] 01
            [34 77 68 69 61 34] "MDE="
        2. 你那个截图我猜得没错是处理的slice类型,而不是slice中的[]byte元素项。

          1. 是当成slice处理了,我认为这个结果不符合预期。

          2. 请问郭老师这个问题解决了吗,在使用redis geopos命令时,经纬度会被base64编码

  3. 当我查询一个正常的 redis set

    数据库中仅存有一个 4

    但是当我取值时我获得了 json.Marsal 后的值,这不是一个正常的表现

    我的代码
    items, err := g.Redis().Ctx(ctx).DoVar("SSCAN", myFollowKey, 0, "match", "*", "count", 1000)
    // value={interface | []string} => 0:"0",1:"["NA=="]" 
    // safe=false

    我没办法上传图片,事实上这是一个很明显的bug

    郭强 


    1. 你把完整的可复现该问题的最小可运行示例代码提个issue呢。