1. 开发环境搭建

  • GOROOT变量值是安装的go路径

  • PATH环境变量就是%GOROOT%\bin路径

  • GOPATH环境变量是工作目录,就是写代码的目录,编译源代码等生成的文件都会放到这个目录下

Note:需要在工作目录下新建三个文件夹,分别是bin、pkg、src;src 目录存放的是我们的go源代码,不同工程项目的代码以包名区分;pkg 中存放编译后生成的文件(比如:.a);bin文件夹存放go install命名生成的可执行文件; 建议把GOPATH/bin加到系统的环境变量path里面,这样就可以直接在终端里使用我们go开发生成的程序

2. 初步配置Redisgo并调试/windows

  • 先安装Git,国内比较快的网址链接https://github.com/waylau/git-for-win
  • 建议在%GOPATH%src中先创建Go工程,如redisTesting
  • 然后在main.go中直接 import redis "github.com/gomodule/redigo/redis";此时,Goland会自动提示安装包的拉取,Redis包就在%GOPATH%pkg目录中。
  • 作为备选,可以在Goland终端中执行 go get -v github.com/gomodule/redigo

在%GOPATH%src的redisTesting工程的mian.go函数中输入测试代码:

package mainimport ("fmt""github.com/gomodule/redigo/redis"
)func main() {// 使用redis封装的Dial进行tcp连接rds,err := redis.Dial("tcp","localhost:32771")errCheck(err)defer rds.Close()//对本次连接进行set操作_,setErr := rds.Do("set","url","xxbandy.github.io")errCheck(setErr)//使用redis的string类型获取set的k/v信息r,getErr := redis.String(rds.Do("get","url"))errCheck(getErr)fmt.Println(r)}func errCheck(err error) {if err != nil {fmt.Println("sorry,has some error:",err)return}
}

进一步:

  • 终端执行 go build main.go 组建
  • 终端执行 go run main.go 运行

3. Redis的Golang接口函数

  • 链接功能

Conn接口是redis操作过程中比较重要的接口。应用一般通过调用Dial、DialWithTimeout、NewConn函数来创建一个链接。Note应用必须在操作redis结束之后去调用该连接的Close方法来关闭连接,以防止资源消耗以及其他问题。

Conn接口的相关方法如下:

type Conn interference{// 关闭链接Close() error// 当连接不可用的情况下,返回非空值Err() error// Do方法是指向redis服务器发送命令 并 返回接收到的命令Do(commandName string, args ...interface{}) (reply interface{}, err error)// Send将相关的命令写入到客户端的buffer中Send(commandName string, arg ...interface{}) error// Flush将客户端的输出缓冲内容刷新到redis服务器端Flush() error// Receive从redis服务端接受单个回复Receive() (reply interface{}, err error)
}

常用的创建Conn的方式:

//    使用Dial函数
// func Dial(network, address string, options ...DialOption) (Conn, error)
/*可选的参数
func DialConnectTimeout(d time.Duration) DialOption
func DialDatabase(db int) DialOption
func DialKeepAlive(d time.Duration) DialOption
func DialNetDial(dial func(network, addr string) (net.Conn, error)) DialOption
func DialPassword(password string) DialOption
func DialReadTimeout(d time.Duration) DialOption
func DialWriteTimeout(d time.Duration) DialOption
*/
rds,err := redis.Dial("tcp","localhost:32771")
defer rds.Close()// 使用DialTimeout函数(默认增加了连接、读写超时时间)
// func DialTimeout(network, address string, connectTimeout, readTimeout, writeTimeout time.Duration) (Conn, error)// 使用NewConn函数(将一个网络连接转换成redis连接)
// func NewConn(netConn net.Conn, readTimeout, writeTimeout time.Duration) Conn
  • Redis命令的执行

一般采用Do()方法执行redis命令操作。

package main
// Redis链接+执行import ("fmt""time"redis "github.com/gomodule/redigo/redis"
)
func main() {// 使用Dial进行tcp连接.设置长连接时间为1s,连接超时时间为5s,读写超时均为1s,并设置密码连接// 由于redis服务器设置了密码,如果密码错误会报异常: ERR invalid passwordrds,err := redis.Dial("tcp","localhost:32771",redis.DialKeepAlive(1*time.Second),redis.DialPassword("ziheng"),redis.DialConnectTimeout(5*time.Second),redis.DialReadTimeout(1*time.Second),redis.DialWriteTimeout(1*time.Second))fmt.Println(err)defer rds.Close()// 使用Conn的Do方法来操作redis命令// Do(commandName string, args ...interface{}) (reply interface{}, err error)// 使用redis的string类型获取set的k/v信息r,getErr := redis.String(rds.Do("get","url"))fmt.Println(getErr)fmt.Println(r)
}
  • 使用Pipelining操作redis

Note:建议使用redis自身包含的命令进行批量操作而不是使用pipelining,比如msetmgethmsethmget等等。原子性可能会更好一些。Conn会使用SendFlushReceive来支持pipeline操作。

Send会写入命令到连接的输出缓冲区里。

Flush会将输出缓冲区中的数据刷新到服务端。

Receive回去服务器端读取单个响应。

rds.Send("SET", "foo", "bar")
rds.Flush()
v, err = rds.Receive()

其实,在Do()方法中包含了SendFlushReceive等方法。例如,使用Send()Do()方法来实现pipeline:

  • 并发处理

一般并发访问redis,社区中大部分专家建议使用安全线程池去获取连接,从一个goroutine中使用和释放一个链接。正如前面提到的,从线程池中获取的连接会有并发限制。

  • 发布/订阅模式(Publish and Subscribe)

使用SendFlushReceive等方法来实现Pub/Sub订阅,例如:

rds.Send("SUBSCRIBE","ANSIBLE-KEY")
rds.Flush()
for {reply,err := rds.Receive()if err != nil {return err}//process pushed message
}

PubSubConn类型用convenience方法包装了一个Conn实现了订阅,Subscribe PSubscribe Unsubscribe PUnsubscribe方法会send并且flush一个订阅管理命令。接收方法会将push的消息转换成一个可以进行switch的合适类型。例如:

psc := redis.PubSubConn{Conn: c}psc.Subscribe("example")
for {switch v := psc.Receive().(type) {case redis.Message:fmt.Printf("%s: message: %s\n", v.Channel, v.Data)case redis.Subscription:fmt.Printf("%s: %s %d\n", v.Channel, v.Kind, v.Count)case error:return v}
}

3. Redigo操作redis的应用场景

  • 使用String和Int获取字符串类型的输出

就是set get mset mget之类的命令。 Note:当获取数字类型的key时需要使用redis.Int()获取数字类型的输出结果。例如,我想获取string类型的name, Int类型的id:

func main() {c,connErr := redisConn("localhost","32771","ziheng")errCheck("connErr",connErr)getV,_ := redis.String(c.Do("get","name"))getV2,_ := redis.Int(c.Do("get","id"))fmt.Println(getV,getV2)  //output1 = "shenziheng"; output2 = "0001" // mget name id 同理
}
  • 使用redis的安全链连接池

使用连接池可以高效的管理redis的连接,并可以方便地控制redis的并发性能。相关结构体/方法/实例如下:

// 相关的结构体和方法
type Pool struct {//创建一个tcp链接的匿名函数Dial func() (Conn, error)//可选的函数,用来对之前使用过的空闲链接进行安全检查TestOnBorrow func(c Conn, t time.Time) error//最大可用链接数MaxIdle int//在给定的时间,最大可分配的连接数。为0则不限制MaxActive int//空闲链接的关闭时间,如果为空,空闲链接不会被关闭IdleTimeout time.Duration//如果Wait为true并且进行MaxActive限制了,Get()将会等待链接被返回Wait bool//关闭老链接的时间区间。如果为空则不会在生命周期内关闭链接MaxConnLifetime time.Duration
}//创建一个Pool结构体
func NewPool(newFn func() (Conn, error), maxIdle int) *Pool
// 获取pool的连接数,包含空闲链接和使用连接
func (p *Pool) ActiveCount() int//关闭并释放pool中的资源
func (p *Pool) Close() error
//从pool中获取一个连接
func (p *Pool) Get() Conn
// 获取空闲链接数
func (p *Pool) IdleCount() int
// 获取连接池的状态信息
func (p *Pool) Stats() PoolStats
type PoolStats struct {ActiveCount intIdleCount   int
}
package main
import ("fmt""time""os""github.com/gomodule/redigo/redis"
)
//构造一个链接函数,如果没有密码,passwd为空字符串
func redisConn(ip,port,passwd string) (redis.Conn, error) {rds,err := redis.Dial("tcp",ip+":"+port,redis.DialConnectTimeout(5*time.Second),redis.DialReadTimeout(1*time.Second),redis.DialWriteTimeout(1*time.Second),redis.DialPassword(passwd),redis.DialKeepAlive(1*time.Second),)return rds,err
}//构造一个错误检查函数
func errCheck(tp string,err error) {if err != nil {fmt.Printf("sorry,has some error for %s.\r\n",tp,err)os.Exit(-1)}
}//构造一个连接池
//url为包装了redis的连接参数ip,port,passwd
func newPool(ip,port,passwd string) *redis.Pool {return &redis.Pool{MaxIdle:            5,    //定义redis连接池中最大的空闲链接为3MaxActive:          18,    //在给定时间已分配的最大连接数(限制并发数)IdleTimeout:        240 * time.Second,MaxConnLifetime:    300 * time.Second,Dial:               func() (redis.Conn,error) { return redisConn(ip,port,passwd) },}
}func main() {//使用newPool构建一个redis连接池pool := newPool("localhost","32771","123qweasd")defer pool.Close()for i := 0;i <= 4;i++ {go func() {//从pool里面获取一个可用的redis连接c := pool.Get()defer c.Close()//mset mgetfmt.Printf("ActiveCount:%d IdleCount:%d\r\n",pool.Stats().ActiveCount,pool.Stats().IdleCount)_,setErr := c.Do("mset","name","biaoge","url","http://xxbandy.github.io")errCheck("setErr",setErr)if r,mgetErr := redis.Strings(c.Do("mget","name","url")); mgetErr == nil {for _,v := range r {fmt.Println("mget ",v)}}}()}time.Sleep(1*time.Second)
}

Go进阶(1): Golang + Goland 研究Redis的基本操作与函数接口相关推荐

  1. Golang + Goland环境配置 + Goland破解

    Golang + Goland环境配置 :https://www.jianshu.com/p/d9cb6b3aacc6 Goland破解:https://blog.csdn.net/u01404481 ...

  2. Go实战--golang中使用redis(redigo和go-redis/redis这个已测试)

    自己做测试了没有问题,虚拟机连不上可以把包下载到本地. 版权声明:本文为博主原创文章,未经博主允许不得转载. http://blog.csdn.net/wangshubo1989/article/de ...

  3. Redis进阶实践之十六 Redis大批量增加数据

    原文:Redis进阶实践之十六 Redis大批量增加数据 一.介绍 有时候,Redis实例需要在很短的时间内加载大量先前存在或用户生成的数据,以便尽可能快地创建数百万个键.这就是所谓的批量插入,本文档 ...

  4. 一个golang编写的redis内存分析工具rma4go

    redis 内存分析工具 rma4go 简介 redis是一个很有名的内存型数据库,这里不做详细介绍.而rma4go (redis memory analyzer for golang) 是一个red ...

  5. Go实战--golang中使用redis(redigo和go-redis/redis)

    生命不止,继续 go go go !!! 以前介绍过golang中如何使用sqlite3: <Go实战–go语言操作sqlite数据库(The way to go)> 今天跟大家分享的是如 ...

  6. python中常用于输出信息的语句函数是print括号_第十四课我们研究一下常用的print()函数,翻看了一下Python宝典...

    很高兴又和大家见面了. 上一节课,我们学会了如何打通任督二脉,突破编程中的瓶颈,小K希望大家遇到问题时,能够冷静下来,认真分析,不要怂. 这两节课的主要内容是带大家探究"熟悉的陌生人&quo ...

  7. Redis的基本操作和运用

    Redis的基本操作和运用 一. 什么是NOSQL? NoSQL(NoSQL = Not Only SQL ),意即"不仅仅是SQL",它泛指非关系型的数据库.随着互联网2003年 ...

  8. GoLang之编译器自动检测类型是否实现接口(5)

    文章目录 GoLang之编译器自动检测类型是否实现接口(5) GoLang之编译器自动检测类型是否实现接口(5) 经常看到一些开源库里会有一些类似下面这种奇怪的用法: var _ io.Writer ...

  9. 华为的mysql数据库如何登陆_华为云数据库GeminiDB高度兼容Redis和InfluxDB两大接口...

    随着云端数据库的蓬勃发展,市面上涌现出越来越多的数据库,如何满足日益增长的客户需求,是每个云厂商必须考虑的问题.华为云数据库聚焦企业,致力于打造企业级数据库,为企业客户提供稳定可靠.安全可信.可持续创 ...

最新文章

  1. c语言文件操作中换行,关于文件操作,碰到空格就换行
  2. JavaGUI中的JComboBox的处理
  3. kafaka生产者消费者demo(简易上手demo)
  4. Swift 3 0 FMDB 初试
  5. 进程间通信:消息队列概念及代码
  6. react jest测试_如何使用Jest和react-testing-library测试Socket.io-client应用程序
  7. 【计算机科学基础】计算机不需要整数减法器的原因
  8. tpcc-mysql percona_tpcc-mysql 对percona5.6进行压力测试
  9. SuperMap/PlottingSymbol
  10. 3位黑洞发现者获2020年诺贝尔物理学奖
  11. vim使用系列之二——总结一下自己常用的VIM操作
  12. SQL 基础面试题(四)
  13. Vue学习笔记之10-组件化开发
  14. State Processor API:如何读取,写入和修改 Flink 应用程序的状态
  15. 图说丨京东《技术重构社会供应链——未来科技趋势白皮书》
  16. 关于奈奎斯特图的一些解读
  17. growup怎么读_欧路词典|英汉-汉英词典 grow up是什么意思_grow up的中文解释和发音_grow up的翻译_grow up怎么读...
  18. C++11时代的标准库快餐教程(4) - 排序算法的应用
  19. anaconda初体验
  20. Technical Artist 的不归路 —— 场景构图中的物件

热门文章

  1. oralce 笔记
  2. ActiveMQ BrokeUrl的配置和消息持久化配置
  3. 马上着手开发 iOS 应用程序-1.1设置
  4. vxworks 学习和windows azure 学习
  5. Effective C# 原则1:尽可能的使用属性(property),而不是数据成员(field)。
  6. nyoj-205--求余数--(大整数取模)
  7. windows下cmake编译VTK到PCL中
  8. Golang的指针类型
  9. Kafka关键参数设置
  10. java概述、安装、配置环境、运行