Redigo: ํ•ด์‹œ ์ง€์› ์ถ”๊ฐ€

์— ๋งŒ๋“  2013๋…„ 03์›” 30์ผ  ยท  7์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: gomodule/redigo

๋‚˜๋Š” Go + redigo์— ํ•ด๋‹นํ•˜๋Š” ๊ฒƒ์„ ์–ป์„ ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.

HMSET myhash field1 "Hello" field2 "World"

์ž‘๋™ํ•˜๋ ค๋ฉด("'hmset' ๋ช…๋ น์— ๋Œ€ํ•œ ์ž˜๋ชป๋œ ์ˆ˜์˜ ์ธ์ˆ˜ ์˜ค๋ฅ˜ ์˜ค๋ฅ˜"). ๋„ค์ดํ‹ฐ๋ธŒ ํ•ด์‹œ ์ง€์›์€ ์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ํŽธ์˜ ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

๋‹ค์Œ์€ 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)
    }
}

๋ชจ๋“  7 ๋Œ“๊ธ€

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 ๋Š” ์ค‘์ฒฉ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ์ข‹์€ ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰