Redigoを使う(5)　ユーティリティ関数

# はじめに

Go言語向けクライアントライブラリ[Redigo](https://github.com/gomodule/redigo)の使い方を見ます。
Redigoでは、簡潔なコーディングのための様々なユーティリティ関数が提供されています。主なものの使い方を紹介します。

# 環境

* OS: Windows 10
* Redis: [win-3.2.100](https://github.com/MicrosoftArchive/redis/releases/tag/win-3.2.100)
* Go言語: [1.11](https://blog.golang.org/go1.11)

# 変数へ変換

サーバからの応答をGoの様々な型に変換する関数です。

整数型に変換するには`Int`や`Int64`や`Uint64`を用います。例えばRedisの文字列型で保存した数値をGETでとるときや、LLENなどの応答に使います。また、浮動小数点型に変換するには`Float64`、文字列型に変換するには`String`、バイトスライスに変換するには`Bytes`を使います。

```go
	var n int
	_, _ = conn.Do("SET", "money", "1000")
	n, _ = redis.Int(conn.Do("GET", "money"))
	fmt.Println(n) // 1000

	_, _ = conn.Do("RPUSH", "city", "tokyo")
	n, _ = redis.Int(conn.Do("LLEN", "city"))
	fmt.Println(n) // 1

	var f float64
	_, _ = conn.Do("SET", "temperature", "25.6")
	f, _ = redis.Float64(conn.Do("GET", "temperature"))
	fmt.Println(f) // 25.6

	var s string
	_, _ = conn.Do("SET", "weather", "rainy")
	s, _ = redis.String(conn.Do("GET", "weather"))
	fmt.Println(s) // rainy

	var b []byte
	_, _ = conn.Do("SET", "alphabet", "abc")
	b, _ = redis.Bytes(conn.Do("GET", "alphabet"))
	fmt.Println(b) // [97 98 99]
```

# スライスへ変換

Redisサーバからの複数のリプライ（Multi bulk reply）をスライスに変換します。全てを同じ型に変換したいときは、`Ints`、`Float64s`、`Strings`、`ByteSlices`などが使えます。`Ints`や`Float64s`は、一つでも型変換に失敗すればエラーが返ります。

```go
	var n []int
	_, _ = conn.Do("MSET", "width", "640", "height", "480")
	n, err = redis.Ints(conn.Do("MGET", "width", "height"))
	fmt.Println(n) // [640 480]

	var f []float64
	_, _ = conn.Do("MSET", "temperature", "25.6", "humidity", "10.3")
	f, _ = redis.Float64s(conn.Do("MGET", "temperature", "humidity"))
	fmt.Println(f) // [25.6 10.3]

	var s []string
	_, _ = conn.Do("RPUSH", "city", "tokyo")
	_, _ = conn.Do("RPUSH", "city", "osaka")
	s, _ = redis.Strings(conn.Do("LRANGE", "city", 0, -1))
	fmt.Println(s) // [tokyo osaka]

	var b [][]byte
	_, _ = conn.Do("RPUSH", "alphabet", "abc")
	_, _ = conn.Do("RPUSH", "alphabet", "def")
	b, _ = redis.ByteSlices(conn.Do("LRANGE", "alphabet", 0, -1))
	fmt.Println(b) // [[97 98 99] [100 101 102]]
```

また異なる型が混ざっているときは、`Values`でinterface{}のスライスに変換させることができます。さらにまとめて変換するには`Scan`が便利です。

```go
	var weight int
	var eyesight float64
	var blood string
	var v []interface{}
	_, _ = conn.Do("SET", "weight", "60")
	_, _ = conn.Do("SET", "eyesight", "1.5")
	_, _ = conn.Do("SET", "blood", "A")
	v, _ = redis.Values(conn.Do("MGET", "weight", "eyesight", "blood"))
	v, _ = redis.Scan(v, &weight, &eyesight, &blood)
	fmt.Println(weight, eyesight, blood) // 60 1.5 A
```

# マップへ変換

HGETALL（ハッシュ型の全てのフィールド名と値のペアを得る）の応答では、フィールド名と値が交互に現れます。これをマップに変換するための関数も用意されています。

```go
	var m map[string]string
	_, _ = conn.Do("HSET", "profile", "name", "yamada")
	_, _ = conn.Do("HSET", "profile", "age", "30")
	_, _ = conn.Do("HSET", "profile", "country", "america")
	m, _ = redis.StringMap(conn.Do("HGETALL", "profile"))
	fmt.Println(m) // map[name:yamada age:30 country:america]

	var p map[string]int
	_, _ = conn.Do("HSET", "cpu", "sys", "10")
	_, _ = conn.Do("HSET", "cpu", "usr", "20")
	_, _ = conn.Do("HSET", "cpu", "wai", "30")
	p, _ = redis.IntMap(conn.Do("HGETALL", "cpu"))
	fmt.Println(p) // map[usr:20 wai:30 sys:10]
```

# 構造体へ変換

HGETALLの結果を構造体に変換することもできます。構造体の定義のところで「redis」タグでフィールド名を指定し、`Values`で得た結果を`ScanStruct`に与えます。

```go
	var v []interface{}
	var p struct {
		Name    string `redis:"name"`
		Age     int    `redis:"age"`
		Country string `redis:"country"`
	}
	_, _ = conn.Do("HSET", "profile", "name", "yamada")
	_, _ = conn.Do("HSET", "profile", "age", "30")
	_, _ = conn.Do("HSET", "profile", "country", "america")
	v, _ = redis.Values(conn.Do("HGETALL", "profile"))
	_ = redis.ScanStruct(v, &p)
	fmt.Println(p) // {yamada 30 america}
```

# おわりに

Redigoの様々なユーティリティ関数の使い方を見ました。

# 参考

* [Redigoを使う(1)　基本的な使い方](https://qiita.com/riverplus/items/c1df770838d3868c3a13)
* [Redigoを使う(2)　様々なデータ型を扱う](https://qiita.com/riverplus/items/04aa969d699c78f58598)
* [Redigoを使う(3)　トランザクションを行う](https://qiita.com/riverplus/items/5379111adda57f9ac18a)
* [Redigoを使う(4)　コネクションプールを使う](https://qiita.com/riverplus/items/12f9b37cf1795d9bdbb1)
* [Redigoを使う(6)　パブリッシュ／サブスクライブ](https://qiita.com/riverplus/items/e31c6da6f5af28d3a3f7)