Donald Feury

redis

Cache all the things

Odysee YouTube


The other day I was looking to see how difficult it would be to utilize Redis in a go program, not for a specific use case, just in general. Turns out, its pretty freakin easy with the help of a few packages.

The one I decided to use to get a feel for it was this package called redigo.

Setup your project

If you don't have go modules initialized in your project, go ahead and do that.

go mod init gitlab.com/dak425/golang-redis-example

After modules is setup, we need to grab our redis client package.

go get github.com/gomodule/redigo

Now we should be all ready to go (hah get it, go... I'll stop now)

Me stopping

Connecting to a Redis instance

First, lets connect to our Redis instance.

conn, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
  // Handle error
}
defer conn.Close()

We use the Dial function to connect to the instance, passing in two arguments. The first is the protocol to use and the second is the address to the redis instance you want to connect to.

Of course handle errors as you deem necessary.

We also add a deferred called to conn.Close() to ensure our connection gets cleaned up when the program finishes.

Running Redis commands

Setting a value

The redigo package doesn't give us command specific functions like HMSet or something like that. It simply gives us a method on our connection object called Do that allows us to build and send a redis command.

_, err = conn.Do(
  "HMSET",
  "podcast:1",
  "title",
  "Tech Over Tea",
  "creator",
  "Brodie Robertson",
  "category",
  "technology",
  "membership_fee",
  9.99,
)
if err != nil {
  // Handle error
}

I'm building a redis command to set multiple fields on a hash with the key of podcast:1

The Do method returns a reply and an error. I wasn't interested in the reply, only if there was a problem setting the hash fields for that key.

Tech Over Tea is an actual podcast done by a guy I've talked to named Brodie Robertson. He tries to mostly stay on tech centered subjects like Linux and crypto.

I went on it a few months ago, you can find the episode here

He has his own channel where he showcases a bunch of neat little Linux programs and utilities. You can check it out here

Reading key values

Now that we have an entry in our Redis instance, lets read some data back out of it.

First, lets get a single field from our hash we just put in there.

title, err := redis.String(conn.Do("HGET", "podcast:1", "title"))
if err != nil {
  // handle error
}

We're using Do again to build and send a redis command but you'll notice its being wrapped in a function called String. What string does it attempt to convert the redis reply into a go string. If it can't, it will return an error that we can check.

Next, lets grab ALL the entire hash.

podcastHash, err := redis.StringMap(conn.Do("HGETALL", "podcast:1"))
if err != nil {
  // handle error
}

We use another of those type conversion functions called StringMap, which, if successful returns us a map[string]string that we can iterate over.

Now, that's fine but you know what would be really nice? If we could unmarshal our redis response into a struct we had defined. Turns out we can do that.

I have a podcast defined here for use.

type Podcast struct {
  Title    string  `redis:"title"`
  Creator  string  `redis:"creator"`
  Category string  `redis:"category"`
  Fee      float64 `redis:"membership_fee"`
}

You'll notice we've given the struct properties a tag. This tag, not unlike the json tag, is used by certain packages to know how to unmarshal our redis reply into our struct's properties.

So how do we unmarshal our reply into the struct using this package? Well it is a two step process. First, we use the Values function from the redigo package to convert our reply into a []interface{}.

values, err := redis.Values(conn.Do("HGETALL", "podcast:1"))
if err != nil {
  // handle error
}

After we have our converted response, we create an instance of our struct, and pass both the response and a pointer to our struct instance to a function called ScanStruct.

var podcast Podcast
err = redis.ScanStruct(reply, &podcast)
if err != nil {
  // handle error
}

Assuming no error occurred, if you print your struct using Printf or other fmt functions, you will see that the struct now has the values from our hash!

Summary

Now you should be able to write and read data from your Redis instance with your go programs. There are some more advanced concepts you can look into regarding this package, such as connection pooling.

Thank you for your time and be sure to check out my other go articles on here and my other videos on my YouTube.

#go #golang #redis