概要
gomodule/redigo は golang から Redis にアクセスするためのライブラリです
Sentinel や Redis Cluster を使う場合に別のライブラリと組み合わせる必要があります
今回は基本的な使い方を紹介します
環境
- CentOS 7.6.1810
- go 1.12.1
- redigo d3876d43bbbeb98b4d67309b4d3eef49438ef74c
基本
まずは基本です
Redis Server に接続して info server
コマンドを実行してみます
- cd $GOPATH/src/github.com/hawksnowlog/a
- vim main.go
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
fmt.Println(redis.String(c.Do("info", "server")))
}
- go fmt github.com/hawksnowlog/a
- go build github.com/hawksnowlog/a
- ./a
Redis Server の情報が文字列として表示されます
Do 関数を使って redis-cli で使うコマンドをそのまま指定します
サブコマンドがある場合は複数の引数として指定します
set/get
次に set/get コマンドを実行してみます
Redis 上では文字列として管理されますが golang 上で扱う場合には適切な型に変更して使います
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
fmt.Println(c.Do("set", "key", "value"))
fmt.Println(redis.String(c.Do("get", "key")))
fmt.Println(c.Do("set", "key2", 0))
fmt.Println(redis.Int(c.Do("get", "key2")))
}
=> value
=> 0
Do 関数で get
したあとで redis.String
や redis.Int
を使って golang 上で扱える型に変換します
このあと紹介しますがリストやハッシュなども同じように変換してから使います
リスト型
rpush や lset, lrange の使い方です
ポイントは redis.Strings
を使って文字列のスライスに変換してあげる点です
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
fmt.Println(c.Do("rpush", "my_list", "a"))
fmt.Println(c.Do("rpush", "my_list", "b"))
fmt.Println(c.Do("lset", "my_list", 0, "A"))
fmt.Println(c.Do("lset", "my_list", 1, "B"))
myList, err := redis.Strings(c.Do("lrange", "my_list", 0, -1))
if err != nil {
fmt.Println(err)
return
}
for i, v := range myList {
fmt.Printf("%d -> %s\n", i, v)
}
}
=> 0 -> A
=> 1 -> B
lset
コマンドはキーで指定したリストが存在しない場合エラーになるのであらかじめ rpush
や lpush
を使ってリストを作成しておきます
あとは range
関数を使ってスライスをループして値を取得すれば OK です
ハッシュ型
あとは代表的な型としてハッシュ型の使い方を紹介します
これは hgetall
コマンドを使って取り出すことで golang 上では map として扱うことができます
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
fmt.Println(c.Do("hset", "my_hash", "key1", "value1"))
fmt.Println(c.Do("hset", "my_hash", "key2", "value2"))
fmt.Println(redis.String(c.Do("hget", "my_hash", "key1")))
myMap, err := redis.StringMap(c.Do("hgetall", "my_hash"))
if err != nil {
fmt.Println(err)
return
}
for k, v := range myMap {
fmt.Printf("%s -> %s\n", k, v)
}
}
=> key1 -> value1
=> key2 -> value2
redis.StringMap
を使ってコンバートすることで golang 上で map として扱うことができます
リストのときもそうでしたが要素は String になっているので数値を扱う場合にはキャストなどの型変換が必要です
ハッシュ型+構造体
最後に構造体を扱う方法を紹介します
ハッシュとして登録したデータを golang の構造体に marshall して golang 上で扱えるようにすることができます
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
type Profile struct {
Name string `redis:"name"`
Age int `redis:"age"`
}
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
fmt.Println(c.Do("hset", "profile", "name", "hawksnowlog"))
fmt.Println(c.Do("hset", "profile", "age", 99))
pMap, err := redis.Values(c.Do("hgetall", "profile"))
if err != nil {
fmt.Println(err)
return
}
p := Profile{}
err = redis.ScanStruct(pMap, &p)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(p.Name)
fmt.Println(p.Age)
}
=> hawksnowlog, 99
ハッシュにマッピングする構造体 (ここでは Profile) を作成しておきます
hgetall
するところまでは同じです
データを取り出したあとで構造体にマッピングするための redis.ScanStruct
を呼び出します
マッピング対象の構造体を引数の二番目に参照として渡します
あとは普通に構造体を扱うようにデータを参照できます
keys からのデータ取得
これもよくあるパターンかなと思います
あるプレフィックスで取得したキーに対してデータを取得する方法です
package main
import (
"fmt"
"github.com/gomodule/redigo/redis"
)
const prefix = "prefix::"
func main() {
c, err := redis.Dial("tcp", "localhost:6379")
if err != nil {
fmt.Println(err)
return
}
defer c.Close()
keys, err := redis.Strings(c.Do("keys", prefix+"*"))
if err != nil {
fmt.Println(err)
return
}
m := make(map[string][]byte)
for _, k := range keys {
v, err := redis.Bytes(c.Do("get", k))
if err != nil {
fmt.Println(err)
return
}
m[k] = v
}
for k, v := range m {
fmt.Printf("%s -> %s\n", k, string(v))
}
}
最後に
redigo の基本的な使い方を紹介しました
今回は Do 関数を使ってコマンドを実行しましたが Send 関数を使えばパイプライン実行することもできます
ポイントはコマンドの実行結果をちゃんと golang で扱えるようにしてあげる点かなと思います
Do 自体は interface{}
を返すので interface の扱いに慣れている人は直接 Do 関数の返り値を扱っても OK だと思います
慣れていない場合には redis.xxx
のコンバート用の関数を使うことをおすすめします
参考サイト