๋๋ Go + redigo์ ํด๋นํ๋ ๊ฒ์ ์ป์ ์ ์์์ต๋๋ค.
HMSET myhash field1 "Hello" field2 "World"
์๋ํ๋ ค๋ฉด("'hmset' ๋ช ๋ น์ ๋ํ ์๋ชป๋ ์์ ์ธ์ ์ค๋ฅ ์ค๋ฅ"). ๋ค์ดํฐ๋ธ ํด์ ์ง์์ ์ด ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ณ ํธ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ ๋ฐ ์ ์ฉํ ๊ฒ์ ๋๋ค.
Redigo๋ HMSET์ ํฌํจํ ๋ชจ๋ ๋ช ๋ น์ ์คํํ ์ ์์ต๋๋ค. HMSET์ ํธ์ถํ๋ ์ฝ๋ ์ค์ ๊ณต์ ํ ์ ์์ต๋๊น?
package main
import (
"fmt"
"github.com/garyburd/redigo/redis"
"log"
)
var (
conn redis.Conn
)
// Connect to Redis
func init() {
var err error
conn, err = redis.Dial("tcp", ":6379")
if err != nil {
log.Fatalf("Couldn't connect to Redis: %v\n", err)
}
}
func main() {
defer conn.Close()
stockData := map[string]map[string]string{
"GOOG": {"company_name":"Google Inc.", "open_price":"803.99", "ask_price":"795.50", "close_price":"802.66", "bid_price":"793.36"},
"MSFT": {"ask_price":"N/A", "open_price":"28.30", "company_name":"Microsoft Corpora", "bid_price":"28.50", "close_price":"28.37"},
}
conn.Send("HMSET", "stocks")
// conn.Send("HMSET")
// conn.Send("stocks")
// var cmd []interface{}
for sym, row := range stockData {
for colName, val := range row {
key := sym + ":" + colName
// cmd = append(cmd, key, val)
conn.Send(key, val)
}
}
// conn.Send("HMSET", cmd...)
reply, err := conn.Do("EXEC")
if err != nil {
log.Fatalf("Error setting hash: %v\n", err)
}
fmt.Printf("reply == %+v\n", reply)
}
์ฃผ์์ conn.Send("HMSET", cmd...)
๋ฅผ ์ฌ์ฉํ์ฌ (๊ฑฐ์) ๋ชจ๋ ๋ช
๋ น์ ํ ๋ฒ์ ๋ณด๋ด๋ ๊ฒ๊ณผ ๊ฐ์ด ๋ด๊ฐ ์๋ํ ๋ค๋ฅธ ๋ฒ์ ์ ๋ณด์ฌ์ค๋๋ค. conn.Send("HMSET", "stocks", cmd...)
๋ ์ปดํ์ผ๋์ง ์์ต๋๋ค.
๋ด๊ฐ ๋ญ ์๋ชปํ๊ณ ์๋์ง ์์?
๋ค์ ์๋ ๊ฐ ๊ธฐํธ์ ๋ํด ํ๋์ ํด์๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
package main
import (
"github.com/garyburd/redigo/redis"
"log"
)
func main() {
conn, err := redis.Dial("tcp", ":6379")
if err != nil {
log.Fatalf("Couldn't connect to Redis: %v\n", err)
}
defer conn.Close()
stockData := map[string]map[string]string{
"GOOG": {"company_name": "Google Inc.", "open_price": "803.99", "ask_price": "795.50", "close_price": "802.66", "bid_price": "793.36"},
"MSFT": {"ask_price": "N/A", "open_price": "28.30", "company_name": "Microsoft Corpora", "bid_price": "28.50", "close_price": "28.37"},
}
// Example 1: Write command arguments out explicitly.
for sym, row := range stockData {
if _, err := conn.Do("HMSET", sym,
"company_name", row["company_name"],
"open_price", row["open_price"],
"ask_price", row["ask_price"],
"bid_price", row["bid_price"]); err != nil {
log.Fatal(err)
}
}
printAndDel(conn, "example 1", stockData)
// Example 2: Construct command arguments using range over a row map.
for sym, row := range stockData {
args := []interface{}{sym}
for k, v := range row {
args = append(args, k, v)
}
if _, err := conn.Do("HMSET", args...); err != nil {
log.Fatal(err)
}
}
printAndDel(conn, "example 2", stockData)
// Example 3: Construct command arguments using Redigo helper function.
for sym, row := range stockData {
if _, err := conn.Do("HMSET", redis.Args{sym}.AddFlat(row)...); err != nil {
log.Fatal(err)
}
}
printAndDel(conn, "example 3", stockData)
}
func printAndDel(conn redis.Conn, message string, stockData map[string]map[string]string) {
log.Print(message)
for sym := range stockData {
values, err := redis.Values(conn.Do("HGETALL", sym))
if err != nil {
log.Fatal(err)
}
log.Print(sym)
for i := 0; i < len(values); i += 2 {
log.Printf(" %s: %s", values[i], values[i+1])
}
}
for sym := range stockData {
if _, err := conn.Do("DEL", sym); err != nil {
log.Fatal(err)
}
}
}
๋ค์์ map ๋์ struct๋ฅผ ์ฌ์ฉํ๋ ๋ ๋ค๋ฅธ ์์ ๋๋ค. ์ด ์์์๋ ์ด์ ์์ ๋์ผํ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.
package main
import (
"github.com/garyburd/redigo/redis"
"log"
)
type Stock struct {
CompanyName string `redis:"company_name"`
OpenPrice string `redis:"open_price"`
AskPrice string `redis:"ask_price"`
ClosePrice string `redis:"close_price"`
BidPrice string `redis:"bid_price"`
}
func main() {
conn, err := redis.Dial("tcp", ":6379")
if err != nil {
log.Fatalf("Couldn't connect to Redis: %v\n", err)
}
defer conn.Close()
stockData := map[string]*Stock{
"GOOG": &Stock{CompanyName: "Google Inc.", OpenPrice: "803.99", AskPrice: "795.50", ClosePrice: "802.66", BidPrice: "793.36"},
"MSFT": &Stock{AskPrice: "N/A", OpenPrice: "28.30", CompanyName: "Microsoft Corpora", BidPrice: "28.50", ClosePrice: "28.37"},
}
for sym, row := range stockData {
if _, err := conn.Do("HMSET", redis.Args{sym}.AddFlat(row)...); err != nil {
log.Fatal(err)
}
}
for sym := range stockData {
values, err := redis.Values(conn.Do("HGETALL", sym))
if err != nil {
log.Fatal(err)
}
var stock Stock
if err := redis.ScanStruct(values, &stock); err != nil {
log.Fatal(err)
}
log.Printf("%s: %+v", sym, &stock)
}
}
์ข์ ์, ๊ฐ์ฌํฉ๋๋ค! ์ข ๋ ์ฝ์ด๋ณด๋ Redis๊ฐ ์ค์ฒฉ ํด์๋ฅผ ์ง์ํ์ง ์๋ ๊ฒ ๊ฐ์์ ๊ธฐํธ์์ ์ฃผ์ ๋ฐ์ดํฐ์ ์ด๋ฅด๋ ๋ค๋ฅธ ํด์๋ฅผ ํฌํจํ๋ ํ๋์ Redis ํด์๋ฅผ ์์ฑํ๋ ค๋ ์๋๊ฐ ์๋ํ์ง ์์ ๊ฒ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค. ๋ด๊ฐ ํ์๋ก ํ๋ ๊ฒ์ด๊ธฐ ๋๋ฌธ์ ์ผ๋ถ JSON์ ๋ฌธ์์ด๋ก ์ ์ฅํ๋ ๊ฝค ๊ด์ฐฎ์ ํดํน์ ์๋ํด ๋ณผ ์ ์์ต๋๋ค.
์ด๋ค ์์ผ๋ก๋ ์ ๋ ์ด ์์ ์ ์ํํ ์ ์์ ๊ฒ์ ๋๋ค. ํนํ ๊ทํ๊ฐ ์ ๊ณตํ ์๋ฅผ ์ฌ์ฉํ๋ฉด ๋์ฑ ๊ทธ๋ ์ต๋๋ค. ๋ค์ ํ๋ฒ ๊ฐ์ฌํฉ๋๋ค!
์ค์ฒฉ ํด์๋ ์ง์๋์ง ์์ต๋๋ค. ๋ฌด๋ฃ ๋ฐ ์งง์ The Little Redis Book ์ Redis์์ ์ง์ํ๋ ์ ํ์ ๋ํ ๋ฉ์ง ๊ฐ์๋ฅผ ์ ๊ณตํฉ๋๋ค.
JSON์ Redis์ ์ ์ฅํ๋ ๊ฒ์ด ์ผ๋ฐ์ ์ ๋๋ค. Go์ ๋ฐ์ดํฐ์๋ง ์ก์ธ์คํ๋ ๊ฒฝ์ฐ ์ธ์ฝ๋ฉ/gob ๋ ์ค์ฒฉ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๋ ๋ค๋ฅธ ์ข์ ์ต์ ์ ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ๋๊ธ
๋ค์์ map ๋์ struct๋ฅผ ์ฌ์ฉํ๋ ๋ ๋ค๋ฅธ ์์ ๋๋ค. ์ด ์์์๋ ์ด์ ์์ ๋์ผํ ํ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํฉ๋๋ค.