go-redis guide (Go)
Connect your Go application to a Redis database
go-redis is the Go client for Redis. The sections below explain how to install go-redis and connect your application to a Redis database.
go-redis requires a running Redis server. See here for Redis Open Source installation instructions.
Install
go-redis supports the last two Go versions. You can only use it from within a Go module, so you must initialize a Go module before you start, or add your code to an existing module:
go mod init github.com/my/repo Use the go get command to install go-redis/v9:
go get github.com/redis/go-redis/v9 Connect
The following example shows the simplest way to connect to a Redis server. First, import the go-redis package:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } Then connect to localhost on port 6379 and add a context object:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } You can also connect using a connection string:
opt, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>") if err != nil { panic(err) } client := redis.NewClient(opt) After connecting, you can test the connection by storing and retrieving a simple string:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } You can also easily store and retrieve a hash:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } Use struct tags of the form redis:"<field-name>" with the Scan() method to parse fields from a hash directly into corresponding struct fields:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } Close the connection when you're done using a Close() call:
package main import ( "context" "fmt" "github.com/redis/go-redis/v9" ) func main() { rdb := redis.NewClient(&redis.Options{ Addr: "localhost:6379", Password: "", // no password DB: 0, // use default DB Protocol: 2, }) ctx := context.Background() err := rdb.Set(ctx, "foo", "bar", 0).Err() if err != nil { panic(err) } val, err := rdb.Get(ctx, "foo").Result() if err != nil { panic(err) } fmt.Println("foo", val) // >>> foo bar hashFields := []string{ "model", "Deimos", "brand", "Ergonom", "type", "Enduro bikes", "price", "4972", } res1, err := rdb.HSet(ctx, "bike:1", hashFields).Result() if err != nil { panic(err) } fmt.Println(res1) // >>> 4 res2, err := rdb.HGet(ctx, "bike:1", "model").Result() if err != nil { panic(err) } fmt.Println(res2) // >>> Deimos res3, err := rdb.HGet(ctx, "bike:1", "price").Result() if err != nil { panic(err) } fmt.Println(res3) // >>> 4972 res4, err := rdb.HGetAll(ctx, "bike:1").Result() if err != nil { panic(err) } fmt.Println(res4) // >>> map[brand:Ergonom model:Deimos price:4972 type:Enduro bikes] type BikeInfo struct { Model string `redis:"model"` Brand string `redis:"brand"` Type string `redis:"type"` Price int `redis:"price"` } var res4a BikeInfo err = rdb.HGetAll(ctx, "bike:1").Scan(&res4a) if err != nil { panic(err) } fmt.Printf("Model: %v, Brand: %v, Type: %v, Price: $%v\n", res4a.Model, res4a.Brand, res4a.Type, res4a.Price) // >>> Model: Deimos, Brand: Ergonom, Type: Enduro bikes, Price: $4972 rdb.Close() } In the common case where you want to close the connection at the end of the function where you opened it, you may find it convenient to use a defer statement right after connecting:
func main() { rdb := redis.NewClient(&redis.Options{ ... }) defer rdb.Close() ... } Observability
go-redis supports OpenTelemetry instrumentation. to monitor performance and trace the execution of Redis commands. For example, the following code instruments Redis commands to collect traces, logs, and metrics:
import ( "github.com/redis/go-redis/v9" "github.com/redis/go-redis/extra/redisotel/v9" ) client := redis.NewClient(&redis.Options{...}) // Enable tracing instrumentation. if err := redisotel.InstrumentTracing(client); err != nil { panic(err) } // Enable metrics instrumentation. if err := redisotel.InstrumentMetrics(client); err != nil { panic(err) } See the go-redis GitHub repo. for more OpenTelemetry examples.
More information
See the other pages in this section for more information and examples. Further examples are available at the go-redis website and the GitHub repository.