Using Redis With Go
Tags: go, redis, tutorial, video
Published: 2020-08-29 16:35:35

{% youtube jqI4g8_11eY %}

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](https://github.com/gomodule/redigo) package called redigo.

## Setup your project

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

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

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

```sh
go get github.com/gomodule/redigo
```

Now we should be all ready to go (hah get it, go... I'll stop now)
![Me stopping](https://media.giphy.com/media/3XiQswSmbjBiU/giphy.gif)

## Connecting to a Redis instance

First, lets connect to our Redis instance.

```go
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.

```go
_, 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](https://www.youtube.com/watch?v=DzXLZpRS0xU)
>
> He has his own channel where he showcases a bunch of neat little Linux programs and utilities. You can check it out [here](https://www.youtube.com/channel/UCld68syR8Wi-GY_n4CaoJGA)

### 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.

```go
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.

```go
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.

```go
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{}`.

```go
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`.

```go
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](https://youtube.com/DonaldFeury?sub_confirmation=1).