redis / go-redis

Redis Go client
https://redis.uptrace.dev
BSD 2-Clause "Simplified" License
19.81k stars 2.34k forks source link

Does go-redis support to get original result format? Eg, zrangewithscores in redis return a one-dimensional array, but in go-redis I get redis.Z slice, I want to get original result #2838

Open TonyStarkIron opened 8 months ago

TonyStarkIron commented 8 months ago

Discussed in https://github.com/redis/go-redis/discussions/2837

Originally posted by **TonyStarkIron** December 18, 2023 My app is a redis proxy to receive redis command and return results, however, go-redis returns redis.Z when command is ZRangeWithScores and other clients can't parse. I want to this result format, ![image](https://github.com/redis/go-redis/assets/30336484/3bcb5d0b-2402-4057-9797-2b6ffdc4bda8) but I get this in go-redis: ![image](https://github.com/redis/go-redis/assets/30336484/252a647d-b54b-4a3d-859a-26c2f9aa0cc8)
TonyStarkIron commented 8 months ago

A scenarios is my app receives redis command from Jedis , then uses go-redis execute command and returns resp result to Jedis . but as for ZRangeWithScores, go-redis gets redis.Z slice, which leads to Jedis Unknown Reply exception.

SoulPancake commented 8 months ago

@TonyStarkIron Essentially we read the reply from Redis and parse it to this more Go-friendly format

func (cmd *ZSliceCmd) readReply(rd *proto.Reader) error { // nolint:dupl
    n, err := rd.ReadArrayLen()
    if err != nil {
        return err
    }

    // If the n is 0, can't continue reading.
    if n == 0 {
        cmd.val = make([]Z, 0)
        return nil
    }

    typ, err := rd.PeekReplyType()
    if err != nil {
        return err
    }
    array := typ == proto.RespArray

    if array {
        cmd.val = make([]Z, n)
    } else {
        cmd.val = make([]Z, n/2)
    }

    for i := 0; i < len(cmd.val); i++ {
        if array {
            if err = rd.ReadFixedArrayLen(2); err != nil {
                return err
            }
        }

        if cmd.val[i].Member, err = rd.ReadString(); err != nil {
            return err
        }

        if cmd.val[i].Score, err = rd.ReadFloat(); err != nil {
            return err
        }
    }

    return nil
}

Any reason you're not trying some post processing to convert the parsed redis.Z slice back into the original one-dimensional array format?