Search code examples
goredispublish-subscriberedigo

Convert Redis subscribe []uint8 output to string


I am using the code mentioned below to get output from Redis Publish-Subscribe. The message passed during the Redis publish a string (test-message).

However, the output that I get during subscribe stage is of type []uint8. Following is the output that I get when I run the below mentioned code [116 101 115 116 45 109 101 115 115 97 103 101] (instead of test-message which is the intended output.

This is caused by this line in the below mentioned code fmt.Println("Output: ", v.Data, reflect.TypeOf(v.Data)).

How can I get correct output that I desire in Subscribe in the aforesaid line (i.e. test-message)? I feel that I may need to convert from []uint8 to string to get the correct output.

My code is given below. I used this good answer as a reference for my code.

package main

import (
    "fmt"
    "log"
    "reflect"
    "time"

    "github.com/gomodule/redigo/redis"
)

func main() {
    fmt.Println("Start redis test.")

    c, err := redis.Dial("tcp", "localhost:6379")
    if err != nil {
        log.Println(err)
    } else {
        log.Println("No error during redis.Dial.")
    }
    // defer c.Close()

    val := "test-message"

    /// Publisher.
    go func() {
        c, err := redis.Dial("tcp", "localhost:6379")
        if err != nil {
            panic(err)
        }

        count := 0
        for {
            c.Do("PUBLISH", "example", val)
            // c.Do("PUBLISH", "example",
            //  fmt.Sprintf("test message %d", count))
            count++
            time.Sleep(1 * time.Second)
        }
    }()
    /// End here

    /// Subscriber.
    psc := redis.PubSubConn{Conn: c}
    psc.Subscribe("example")

    for {
        switch v := psc.Receive().(type) {
        case redis.Message:
            //fmt.Printf("%s: message: %s\n", v.Channel, v.Data)
            fmt.Println("Output: ", v.Data, reflect.TypeOf(v.Data))
        case redis.Subscription:
            fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)
        case error:
            fmt.Println(v)
        }

        time.Sleep(1)
    }
    /// End here

}

Solution

  • []uint8 is synonymous with []byte and a byte slice can be converted to string using a conversion expression.

    1. Converting a slice of bytes to a string type yields a string whose successive bytes are the elements of the slice.
    string([]byte{'h', 'e', 'l', 'l', '\xc3', '\xb8'})   // "hellø"
    string([]byte{})                                     // ""
    string([]byte(nil))                                  // ""
    
    type MyBytes []byte string(MyBytes{'h', 'e', 'l', 'l', '\xc3',
    '\xb8'})  // "hellø"
    

    So the following should be enough:

    string(v.Data)
    

    You can also print the string without conversion by using the %s verb in fmt:

    fmt.Printf("Output: %s", v.Data)
    

    Example: https://play.golang.org/p/JICYPfOt-fQ

    data := []uint8(`test-message`)
    fmt.Println(data)
    fmt.Println(string(data))
    fmt.Printf("%s\n", data)