Skip to content

Instantly share code, notes, and snippets.

@massenz
Last active March 20, 2022 19:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save massenz/bd6c886f9236fd326478d9b560e13070 to your computer and use it in GitHub Desktop.
Save massenz/bd6c886f9236fd326478d9b560e13070 to your computer and use it in GitHub Desktop.
Serialize data to/from Redis in a custom type
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/go-redis/redis/v8"
"os"
"time"
)
// Baby is a simple demo data struct
type Baby struct {
Name string
DateOfBirth time.Time
}
// MarshalBinary is needed to encode the data before storing in Redis,
// and to retrieve it later.
//
// **NOTE** the receiver must be a concrete type (NOT a pointer) of the
// serialization to Redis will fail.
func (i Baby) MarshalBinary() ([]byte, error) {
// Obviously it makes no sense to serialize to JSON to store in Redis,
// but the same approach would work with, for example, Protobuf messages
// with an efficent binary encoding.
return json.Marshal(i)
}
// UnmarshalBinary is the dual of MarshalBinary and will parse the
// binary data into the receiver.
// See: https://pkg.go.dev/encoding
func (i *Baby) UnmarshalBinary(data []byte) error {
return json.Unmarshal(data, i)
}
func main() {
// To run Redis as a container, see: https://hub.docker.com/_/redis/
//
// To connect from the client, see:
// https://redis.uptrace.dev/guide/server.html#connecting-to-redis-server
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
// Creates a Context which will time out after 200ms
// See: https://go.dev/blog/context
timeout, _ := time.ParseDuration("200ms")
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
// Congratulations to mum & dad!
baby := Baby{
Name: "Charlie",
DateOfBirth: time.Now(),
}
start := time.Now()
cmd := rdb.Set(ctx, "charlie", baby, timeout)
val, err := cmd.Result()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
// This will just emit `OK`
fmt.Println(val)
getCmd := rdb.Get(ctx, "charlie")
data, err := getCmd.Bytes()
if err == redis.Nil {
fmt.Println("No babies found!")
} else if err != nil {
fmt.Println(err)
os.Exit(1)
} else {
var baby Baby
err = baby.UnmarshalBinary(data)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
fmt.Println(baby)
}
fmt.Printf("Took %q\n", time.Since(start))
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment