Go

How to Implement Redis in Go

Dec 08, 2021
hackajob Staff

You asked and we listened - how do you implement Redis in Go? Don't worry, we get into it in this easy tech tutorial. First, let's talk about what Redis is. As always if you're here just for the tutorial scroll down a little further. If you're interested in what Redis is, keep reading.

What is Redis?

Redis, short for Remote Dictionary Server; positions itself more as a data structure server. In fact, Redis is originally an open-source NoSQL database that holds data in memory. So this means that Redis is actually not just a simple key-value server.

One of the most important differences from other alternatives is Redis' ability to store and use high-level data structures. These data structures are the basic data structures most developers are familiar with (list, map, set). Redis's performance, simplicity and atomic manipulation of data structures, and its capabilities in solving problems that cause performance problems when applied with traditional relational databases provide developers with great convenience.

So earleeir we mentioned that Redis is an in-memory database. What this means for you is that Redis stores your data on RAM memory. However, you can save the data to the disk at certain time intervals depending on your request. In this way, you also ensure data consistency (which is something we all want!).Another advantage of Redis keeping your data in memory is that it can reduce read and write operations to milliseconds.

Redis Data Types

  • String
  • Hash
  • List
  • Set
  • Sorted Set

Some Usage Scenarios of Redis

Caching Mechanism

Caching our frequently used data instead of constantly going to the database or other resources will make a positive contribution in terms of performance. Redis, which can work in a distributed architecture, is used in many applications for distributed cache (distributed caching) management.

Session Management
While using our applications, we frequently use sessions to move our data of users or other structures between pages, but as our application grows, keeping this data causes increased memory space. Redis also plays a role in keeping session information in areas such as social media, e-commerce applications, games.

Pub/Sub
Redis also has commands that support the pub/sub-function and allows Redis to broadcast. This allows a single client to broadcast the message to many other clients connected to a channel.

Queues
Redis supports putting jobs that would take time to complete into a queue structure and then processing them.

redis-1

Right, now you know all about Redis, let's move on to the Go implementation!

We will use go-redis to connect to Redis server which you can get from here: github.com/go-redis/redis
Ok, now let's write some code.

First, let's connect to the redis server.

func connectRedis(ctx context.Context) {
	client := redis.NewClient(&redis.Options{
		Addr: "localhost:6379",
		Password: "",
		DB: 0,
	})

	pong, err := client.Ping(ctx).Result()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(pong)

    redisClient = client
}

Create a function called conenctRedis., this function takes context, we will create context with context.Bakground() where we call connectRedis.. (For more information about the context package, you can check here: https://blog.golang.org/context.)

Now le'ts define a new client from the Redis package and set the default settings. Then let's check whether the connection is provided correctly with the ping function. If there is an error, we print the error on the screen. If there is no problem, we print the pong variable to the screen and expect to see PONG as the output. Finally, let's set the client object to the redisCLient variable that we defined globally.

Now let's save things to redis and try to get them going:

func setToRedis(ctx context.Context, key, val string) {
	err := redisClient.Set(ctx, key, val, 0).Err()
	if err != nil {
		fmt.Println(err)
	}
}

Again, our function takes a context object, since we call all our functions from the same place, we'll send the same context object to all of them. Using the set function, we can set whatever we want as the key-value.

Now let's try to get the values we set :

func getFromRedis(ctx context.Context, key string) string{
	val, err := redisClient.Get(ctx, key).Result()
	if err != nil {
		fmt.Println(err)
	}

	return val
}

Yes, again we use context object :). Since we set it as a key-value, we 'll search for the values we set as keys. We gave the name as the key, so we enter the name and return value.

Now let's write a function that will fetch all the keys:

func getAllKeys(ctx context.Context, key string) []string{
	keys := []string{}

	iter := redisClient.Scan(ctx, 0, key, 0).Iterator()
	for iter.Next(ctx) {
		keys = append(values, iter.Val())
	}
	if err := iter.Err(); err != nil {
		fmt.Println(err)
	}

	return values
}

Using redisClient's Scan function, we can retrieve all key records containing the entered key. We create a string array and after each iteration, we append keys to this string array.

Now, let's combine all:

package main

import (
	"context"
	"fmt"
	"github.com/go-redis/redis"
)

var redisClient *redis.Client

func main() {
	ctx := context.TODO()
	connectRedis(ctx)

	setToRedis(ctx, "name", "redis-test")
	setToRedis(ctx, "name2", "redis-test-2")
	val := getFromRedis(ctx,"name")

	fmt.Printf("First value with name key : %s \n", val)

	values := getAllKeys(ctx, "name*")

	fmt.Printf("All values : %v \n", values)

}

func connectRedis(ctx context.Context) {
	client := redis.NewClient(&redis.Options{
		Addr: "localhost:6379",
		Password: "",
		DB: 0,
	})

	pong, err := client.Ping(ctx).Result()
	if err != nil {
		fmt.Println(err)
	}
	fmt.Println(pong)

	redisClient = client
}

func setToRedis(ctx context.Context, key, val string) {
	err := redisClient.Set(ctx, key, val, 0).Err()
	if err != nil {
		fmt.Println(err)
	}
}

func getFromRedis(ctx context.Context, key string) string{
	val, err := redisClient.Get(ctx, key).Result()
	if err != nil {
		fmt.Println(err)
	}

	return val
}

func getAllKeys(ctx context.Context, key string) []string{
	keys := []string{}

	iter := redisClient.Scan(ctx, 0, key, 0).Iterator()
	for iter.Next(ctx) {
		keys = append(keys, iter.Val())
	}
	if err := iter.Err(); err != nil {
		panic(err)
	}

	return keys
}

That's it, you're getting the hang of it! So we've added two records named name and name2 and we can call getAllKeys function. Let's run it and see the result :

result

Amazing! Of course, Redis isn't just this, there are many things that Redis can do. We've just made a brief introduction here. Want more? We'll be back soon with another tutorial.

References

https://redis.io/documentation
https://redis.uptrace.dev/

Like what you've read or want more like this? Let us know! Email us here or DM us: Twitter, LinkedIn, Facebook, we'd love to hear from you.