go语言使用redis(redigo)

go的redis client用的比较多两个包是redix和redigo,因为beego cache模块里redis使用的是redigo,所以我也就使用这个包了。因为代码内容偏多,结构不清晰,不方便阅读,最后整理成一份思维导图,便于学习。当把整体分析,会发现提供给开发者使用的内容非常巧妙。

image.png

点击下载

Demo:

package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
    "log"
)

func main() {
    c1, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        log.Fatalln(err)
    }
    defer c1.Close()
    c2, err := redis.DialURL("redis://127.0.0.1:6379")
    if err != nil {
        log.Fatalln(err)
    }
    defer c2.Close()


    rec1, err := c1.Do("Get", "name")
    fmt.Println(string(rec1.([]byte)))

    c2.Send("Get", "name")
    c2.Flush()
    rec2, err := c2.Receive()
    fmt.Println(string(rec2.([]byte)))
}

下面内容是更加详细的源码分析

提供给开发者使用的内容
(1)变量
(2)常量
(3)新类型
(4)接口
(5)结构体
(6)函数

1、变量
var ErrNil = errors.New("redigo: nil returned")
2、常量
3、新类型
(1)type Args []interface{}
(2)type Error string
4、接口
(1)Conn
(2)ConnWithTimeout
(3)Scanner
(4)Argument
5、结构体
(1)DialOption
(2)Pool
(3)PoolStats
(4)Subscription
(5)PubSubConn
(6)Message
(7)Script
(8)Pong
6、函数
(1)func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
(2)func NewScript(keyCount int, src string) *Script
(3)func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn
(4)func NewLoggingConnFilter(conn Conn, logger log.Logger, prefix string, skip func(cmdName string) bool) Conn
(5)func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error)
(6)func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error)
(7)func Int(reply interface{}, err error) (int, error)
(8)func Int64(reply interface{}, err error) (int64, error)
(9)func Uint64(reply interface{}, err error) (uint64, error)
(10)func Float64(reply interface{}, err error) (float64, error)
(11)func String(reply interface{}, err error) (string, error)
(12)func Bytes(reply interface{}, err error) ([]byte, error)
(13)func Bool(reply interface{}, err error) (bool, error)
(14)func MultiBulk(reply interface{}, err error) ([]interface{}, error)
(15)func Values(reply interface{}, err error) ([]interface{}, error)
(16)func Float64s(reply interface{}, err error) ([]float64, error)
(17)func Strings(reply interface{}, err error) ([]string, error)
(18)func ByteSlices(reply interface{}, err error) ([][]byte, error)
(19)func Int64s(reply interface{}, err error) ([]int64, error)
(20)func Ints(reply interface{}, err error) ([]int, error)
(21)func StringMap(result interface{}, err error) (map[string]string, error)
(22)func IntMap(result interface{}, err error) (map[string]int, error)
(23)func Int64Map(result interface{}, err error) (map[string]int64, error)
(24)func Positions(result interface{}, err error) ([]
[2]float64, error)
(25)func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error)
(26)func DialReadTimeout(d time.Duration) DialOption
(27)func DialWriteTimeout(d time.Duration) DialOption
(28)func DialConnectTimeout(d time.Duration) DialOption
(29)func DialKeepAlive(d time.Duration) DialOption
(30)func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
(31)func DialDatabase(db int) DialOption
(32)func DialPassword(password string) DialOption
(33)func DialTLSConfig(c *tls.Config) DialOption
(34)func DialTLSSkipVerify(skip bool) DialOption

一、变量
var ErrNil = errors.New("redigo: nil returned")
暴露给开发者的目的是,因为从redis服务器获取数据的时候可能遇到值为空的情况。
二、常量
三、新类型
(1)type Args []interface{}

type Args []interface{}

func (args Args) Add(value ...interface{}) Args
// Add是直接将值追加到args后面的结果返回,但是并不会修改到args
func (args Args) AddFlat(v interface{}) Args 
// AddFlat根据值的类型存储,分为以下五种情况:Struct、Slice、Map、Ptr、其他类型
(1)Struct:
package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

type Ints struct {
    A int
    b int
    C float32
}

func (Ints)Add() {
    fmt.Println(123)
}

func main() {
    i := Ints{1,2,1.2}
    args := redis.Args{1,2,3}
    args1 := args.AddFlat(i)
    fmt.Println(args, len(args))
    fmt.Println(args1, len(args1))
}
输出:
[1 2 3] 3
[1 2 3 A 1 C 1.2] 7
(2)Slice:
package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

func main() {
    i := []int{1,2,12}
    args := redis.Args{1,2,3}
    args1 := args.AddFlat(i)
    fmt.Println(args, len(args))
    fmt.Println(args1, len(args1))
}
输出:
[1 2 3] 3
[1 2 3 1 2 12] 6
(3)Map:
package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

func main() {
    i := map[int]string{1:"你好",2:"测试"}
    args := redis.Args{1,2,3}
    args1 := args.AddFlat(i)
    fmt.Println(args, len(args))
    fmt.Println(args1, len(args1))
}
输出:
[1 2 3] 3
[1 2 3 1 你好 2 测试] 7
(4)Prt
package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

func main() {
    a := 123
    i := &a
    args := redis.Args{1,2,3}
    args1 := args.AddFlat(i)
    fmt.Println(args, len(args))
    fmt.Println(args1, len(args1))
}
输出:
[1 2 3] 3
[1 2 3 0xc00008a2d8] 4
(5)其他类型:
package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
)

type Int int8

func main() {
    a := 123
    b := Int(8)
    args := redis.Args{1,2,3}
    args1 := args.AddFlat(a)
    args1 = args1.AddFlat(b)
    fmt.Println(args, len(args))
    fmt.Println(args1, len(args1))
}
输出:
[1 2 3] 3
[1 2 3 123 8] 5

(2)type Error string

type Error string
func (err Error) Error() string { return string(err) }

四、接口
(1)Conn
(2)ConnWithTimeout
(3)Scanner
(4)Argument
五、结构体
(1)DialOption
源码:

type DialOption struct {
    f func(*dialOptions)
}

作用:该结构体是被设计成 当创建与redis服务器连接时,进行参数设置。
与该结构体有关的函数:

(1)func DialReadTimeout(d time.Duration) DialOption
设置读超时时间
(2)func DialWriteTimeout(d time.Duration) DialOption
设置读超时时间
(3)func DialConnectTimeout(d time.Duration) DialOption
设置连接超时时间
(4)func DialKeepAlive(d time.Duration) DialOption 
(5)func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
(6)func DialDatabase(db int) DialOption
设置连接数据库
(7)func DialPassword(password string) DialOption
设置连接redis密码
(8)func DialTLSConfig(c *tls.Config) DialOption
设置TLS配置信息
(9)func DialTLSSkipVerify(skip bool) DialOption
是否跳过TLS验证
(10)func DialUseTLS(useTLS bool) DialOption
是否使用TLS

(2)Pool
源码:

type Pool struct {
    Dial func() (Conn, error)
    TestOnBorrow func(c Conn, t time.Time) error
    MaxIdle int
    MaxActive int
    IdleTimeout time.Duration
    Wait bool
    MaxConnLifetime time.Duration
    chInitialized uint32
    mu     sync.Mutex 
    closed bool 
    active int 
    ch     chan struct{} 
    idle   idleList
}

作用:用来管理redis连接池
相关函数:

(1)func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
            创建一个连接池对象
(2)func (p *Pool) Get() Conn
            获取一个连接 
(3)func (p *Pool) Stats() PoolStats
            获取池的状态
(4)func (p *Pool) ActiveCount() int
            获取存活数量
(5)func (p *Pool) IdleCount() int
            获取空闲数量
(6)func (p *Pool) Close() error
            关闭

(3)PoolStats
源码:

type PoolStats struct {
    ActiveCount int 
    IdleCount int
}

作用:记录redis池中存活连接数量和空闲连接数
(4)Subscription
源码:

type Subscription struct {
    Kind string          
    Channel string  
    Count int
}

作用:Subscription用于订阅或取消订阅通知。
相关函数:

Demo:

package main

import (
    "fmt"
    "github.com/gomodule/redigo/redis"
    "log"
    "reflect"
)

func main() {
    rc, err := redis.Dial("tcp", "127.0.0.1:6379")
    if err != nil {
        log.Fatalln(err)
    }
    defer rc.Close()

    rc.Send("SUBSCRIBE", "example")
    rc.Flush()
    for {
        reply, err := redis.Values(rc.Receive())
        if err != nil {
            fmt.Println(err)
        }
        if len(reply) == 3 {
            if reflect.TypeOf(reply[2]).String() == "[]uint8" {
                fmt.Println(string(reply[2].([]byte)))
            }
        }
    }
}

(5)PubSubConn
源码:

type PubSubConn struct {
    Conn Conn
}

相关函数:

(1)func (c PubSubConn) Subscribe(channel ...interface{}) error
            订阅给定的一个或多个频道的信息。
(2)func (c PubSubConn) PSubscribe(channel ...interface{}) error
            订阅一个或多个符合给定模式的频道。
(3)func (c PubSubConn) Unsubscribe(channel ...interface{}) error
            指退订给定的频道。
(4)func (c PubSubConn) PUnsubscribe(channel ...interface{}) error
            退订所有给定模式的频道。
(5)func (c PubSubConn) Ping(data string) error 
            测试客户端是否能够继续连通
(6)func (c PubSubConn) Receive() interface{}
             获取回复信息
(7)func (c PubSubConn) ReceiveWithTimeout(timeout time.Duration) interface{}
             在指定时间内获取时间
(8)func (c PubSubConn) Close() error 
              关闭

(6)Message
源码:

type Message struct {
    Channel string    // 频道名称
    Pattern string      // 频道模式
    Data []byte            // 数据
}

(7)Script
源码:

type Script struct {
    keyCount int
    src               string
    hash           string
}

相关函数:

(1)func NewScript(keyCount int, src string) *Script 
(2)func (s *Script) Hash() string
(3)func (s *Script) Do(c Conn, keysAndArgs ...interface{}) (interface{}, error) 
(4)func (s *Script) SendHash(c Conn, keysAndArgs ...interface{}) error 
(5)func (s *Script) Send(c Conn, keysAndArgs ...interface{}) error 
(6)func (s *Script) Load(c Conn) error 

(8)Pong
源码:

type Pong struct {
    Data string
}

(6)函数

(1)func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
(2)func NewScript(keyCount int, src string) *Script 
(3)func NewLoggingConn(conn Conn, logger *log.Logger, prefix string) Conn
(4)func NewLoggingConnFilter(conn Conn, logger *log.Logger, prefix string, skip func(cmdName string) bool) Conn
(5)func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error)
(6)func DoWithTimeout(c Conn, timeout time.Duration, cmd string, args ...interface{}) (interface{}, error)
(7)func Int(reply interface{}, err error) (int, error)
(8)func Int64(reply interface{}, err error) (int64, error)
(9)func Uint64(reply interface{}, err error) (uint64, error)
(10)func Float64(reply interface{}, err error) (float64, error)
(11)func String(reply interface{}, err error) (string, error)
(12)func Bytes(reply interface{}, err error) ([]byte, error)
(13)func Bool(reply interface{}, err error) (bool, error) 
(14)func MultiBulk(reply interface{}, err error) ([]interface{}, error) 
(15)func Values(reply interface{}, err error) ([]interface{}, error)
(16)func Float64s(reply interface{}, err error) ([]float64, error)
(17)func Strings(reply interface{}, err error) ([]string, error) 
(18)func ByteSlices(reply interface{}, err error) ([][]byte, error)
(19)func Int64s(reply interface{}, err error) ([]int64, error)
(20)func Ints(reply interface{}, err error) ([]int, error)
(21)func StringMap(result interface{}, err error) (map[string]string, error) 
(22)func IntMap(result interface{}, err error) (map[string]int, error)
(23)func Int64Map(result interface{}, err error) (map[string]int64, error)
(24)func Positions(result interface{}, err error) ([]*[2]float64, error)
(25)func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error) 
(26)func DialReadTimeout(d time.Duration) DialOption
(27)func DialWriteTimeout(d time.Duration) DialOption
(28)func DialConnectTimeout(d time.Duration) DialOption
(29)func DialKeepAlive(d time.Duration) DialOption 
(30)func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
(31)func DialDatabase(db int) DialOption
(32)func DialPassword(password string) DialOption
(33)func DialTLSConfig(c *tls.Config) DialOption
(34)func DialTLSSkipVerify(skip bool) DialOption

经过学习源码发现,这些顶尖的设计者与我们普通开发者的区别在于,他们包设计非常巧妙,以及只把有必要的内容提供给开发者。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,332评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,508评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,812评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,607评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,728评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,919评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,071评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,802评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,256评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,576评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,712评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,389评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,032评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,798评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,026评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,473评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,606评论 2 350