Beego: 原生方式使用MySQL
package controllers
import (
"database/sql"
"fmt"
"github.com/astaxie/beego"
_ "github.com/go-sql-driver/mysql"
)
type MysqlController struct {
beego.Controller
}
func (c *MysqlController) Get() {
// 连接数据库
db, err := sql.Open("mysql", "root:Pd940810@tcp(127.0.0.1:3306)/test?charset=utf8")
if err != nil {
beego.Info("连接数据库出错", err)
return
}
// 关闭数据库连接
defer db.Close()
// 创建表
_, err = db.Exec("create table userInfo(id int not null auto_increment primary key, name varchar(11) unique)")
if err != nil {
fmt.Printf("创建表出错:%v", err)
return
}
// 插入数据
_, err = db.Exec("insert into userInfo (name) values (?)", "乔治")
if err != nil {
fmt.Printf("创建表出错:%v", err)
return
}
// 查询数据
rows, err := db.Query("select * from userInfo")
type UserInfo struct {
Id int
Name string
}
var u UserInfo
for rows.Next() {
err = rows.Scan(&u.Id, &u.Name)
fmt.Println(u)
}
// 更新数据
_, err = db.Exec("update userInfo set name='pd' where id=1")
c.Ctx.WriteString("testing...")
}
controllers/mysql.go
Redis
REmote DIctionary Server(Redis) 是一个由Salvatore Sanfilippo写的key-value存储系统。
安装
Window 下安装
Redis 支持 32 位和 64 位。这个需要根据你系统平台的实际情况选择
启动服务器端
打开一个cmd窗口 使用cd命令切换目录到redis根目录(例如 C:\redis) 运行
//默认启动
redis-server.exe
//根据修改的配置文件启动
redis-server.exe redis.conf
运行客户端
切换到 redis 目录下运行:
redis-cli.exe -h 127.0.0.1 -p 6379 //127.0.0.1 是本机 IP ,6379 是 redis 服务端口。
//测试
redis> set myKey abc
OK
redis> get myKey
abc
$ wget http://download.redis.io/releases/redis-5.0.5.tar.gz
$ tar xzf redis-5.0.5.tar.gz
$ cd redis-5.0.5
$ make
make完后 redis-5.0.5目录下会出现编译后的redis服务程序redis-server,还有用于测试的客户端程序redis-cli,两个程序位于安装目录 src 目录下:
启动redis服务.
//默认启动
$ ./redis-server //注意这种方式启动redis 使用的是默认配置。也可以通过启动参数告诉redis使用指定配置文件使用下面命令启动。
//根据修改的配置文件启动
$ cd src
$ ./redis-server ../redis.conf //redis.conf 是一个默认的配置文件。我们可以根据需要使用自己的配置文件。
运行客户端测试
$ cd src
$ ./redis-cli
//测试
redis> set foo bar
OK
redis> get foo
"bar"
配置
Redis 的配置文件位于 Redis 安装目录下,文件名为 redis.conf(Windows 名为 redis.windows.conf)。
查看配置
你可以通过 CONFIG 命令查看或设置配置项。
CONFIG GET 命令基本语法:
redis 127.0.0.1:6379> CONFIG GET CONFIG_SETTING_NAME
......
//使用 * 号获取所有配置项:
redis 127.0.0.1:6379> CONFIG GET *
编辑配置
可以通过修改 redis.conf 文件或使用 CONFIG set 命令来修改配置。
CONFIG SET 命令基本语法:
redis 127.0.0.1:6379> CONFIG SET CONFIG_SETTING_NAME NEW_CONFIG_VALUE
OK
参数说明
数据类型
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。
Redis 命令参考
Golang 操作 Redis
安装第三方开源 Redis 库
使用第三方开源的 redis 库: github.com/garyburd/redigo/redis
其他golang可用的第三方开源库:
1. https://github.com/go-redis/redis
2. https://github.com/gomodule/redigo
在使用 Redis 前,先安装第三方 Redis 库,在 GOPATH 路径下执行安装指令:
$GOPATH >go get github.com/garyburd/redigo/redis
//特别说明: 在安装 Redis 库前,确保已经安装并配置了 Git, 因为 是从 github 下载安装 Redis 库的,需要使用到 Git。 如果没有安装配置过 Git,请参考: 如何安装配置 Git
引入包 "github.com/garyburd/redigo/redis"
import "github.com/garyburd/redigo/redis" //引入redis包
Golang对Redis基本操作
链接到 redis
conn, err := redis.Dial("tcp", "127.0.0.1:6379")
通过go 向redis写入数据
通过go 向redis读取数据 (因为返回 r是 interface{},我们需要转换成相应的值类型)
//写入字符串类型
_, err = conn.Do("Set", "name", "tom")
//读取String类型
r, err := redis.String(conn.Do("Get", "name"))
//列表类型
_, err = conn.Do("LPUSH", "list1", "ele1","ele2","ele3")
res, err := redis.String(conn.Do("LPOP", "list1"))
//hash类型
_, err = conn.Do("HSet", "user", "name", "john")
r1, err := redis.String(conn.Do("HGet","user", "name"))
_, err = conn.Do("HSet", "user", "age", 18)
r2, err := redis.Int(conn.Do("HGet","user", "age"))
//多个值
_, err = conn.Do("HMSet", "user", "name", "john", "age", 19)
//多个值
r, err := redis.Strings(conn.Do("HMGet","user02", "name", "age"))
for i, v := range r {
fmt.Printf("r[%d]=%s\n", i, v)
}
通过 Go给 key-value 设置有效时间
//给 name 数据设置有效时间为 10s
_, err = c.Do("expire", "name", 10)
关闭链接
conn.Close()
Redis 链接池
通过 Golang 对 Redis 操作, 还可以通过 Redis 链接池, 流程如下:
事先初始化一定数量的链接,放入到链接池
当 Go 需要操作 Redis 时,直接从 Redis 链接池取出链接即可。
这样可以节省临时获取 Redis 链接的时间,从而提高效率.
//定义一个全局的pool
var pool *redis.Pool
//当启动程序时,就初始化连接池
func init() {
pool = &redis.Pool{
MaxIdle: 8, //最大空闲链接数
MaxActive: 0, // 表示和数据库的最大链接数, 0 表示没有限制
IdleTimeout: 100, // 最大空闲时间
Dial: func() (redis.Conn, error) { // 初始化链接的代码, 链接哪个ip的redis
return redis.Dial("tcp", "localhost:6379")
},
}
}
func main() {
//先从pool 取出一个链接
conn := pool.Get()
defer conn.Close()
...
//我们要从pool 取出链接,一定保证链接池是没有关闭
//如果pool.Close(),则无法获取链接
}
Pipelining(管道)
Redis 管道技术可以在服务端未响应时,客户端可以继续向服务端发送请求,并最终一次性读取所有服务端的响应。
管道操作可以理解为并发操作,并通过Send(),Flush(),Receive()三个方法实现。
客户端可以使用send()方法一次性向服务器发送一个或多个命令,命令发送完毕时,使用flush()方法将缓冲区的命令输入一次性发送到服务器,客户端再使用Receive()方法依次按照先进先出的顺序读取所有命令操作结果。
管道技术最显著的优势是提高了 redis 服务的性能。
Send(commandName string, args ...interface{}) error
Flush() error
Receive() (reply interface{}, err error)
Send:发送命令至缓冲区
Flush:清空缓冲区,将命令一次性发送至服务器
Recevie:依次读取服务器响应结果,当读取的命令未响应时,该操作会阻塞。
package main
import (
"github.com/garyburd/redigo/redis"
"fmt"
)
func main() {
conn,err := redis.Dial("tcp","10.1.210.69:6379")
if err != nil {
fmt.Println("connect redis error :",err)
return
}
defer conn.Close()
conn.Send("HSET", "student","name", "wd","age","22")
conn.Send("HSET", "student","Score","100")
conn.Send("HGET", "student","age")
conn.Flush()
res1, err := conn.Receive()
fmt.Printf("Receive res1:%v \n", res1)
res2, err := conn.Receive()
fmt.Printf("Receive res2:%v\n",res2)
res3, err := conn.Receive()
fmt.Printf("Receive res3:%s\n",res3)
}
控制台打印结果:
Receive res1:0
Receive res2:0
Receive res3:22
发布/订阅
redis本身具有发布订阅的功能,其发布订阅功能通过命令SUBSCRIBE(订阅)/PUBLISH(发布)实现,并且发布订阅模式可以是多对多模式还可支持正则表达式,发布者可以向一个或多个频道发送消息,订阅者可订阅一个或者多个频道接受消息。
package main
import (
"github.com/garyburd/redigo/redis"
"fmt"
"time"
)
func Subs() { //订阅者
conn, err := redis.Dial("tcp", "10.1.210.69:6379")
if err != nil {
fmt.Println("connect redis error :", err)
return
}
defer conn.Close()
psc := redis.PubSubConn{conn}
psc.Subscribe("channel1") //订阅channel1频道
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:
fmt.Println(v)
return
}
}
}
func Push(message string) { //发布者
conn, _ := redis.Dial("tcp", "10.1.210.69:6379")
_,err1 := conn.Do("PUBLISH", "channel1", message)
if err1 != nil {
fmt.Println("pub err: ", err1)
return
}
}
func main() {
go Subs()
go Push("this is wd")
time.Sleep(time.Second*3)
}
控制台打印结果:
channel1: subscribe 1
channel1: message: this is wd
事务操作
MULTI, EXEC,DISCARD和WATCH是构成Redis事务的基础,当然我们使用go语言对redis进行事务操作的时候本质也是使用这些命令。
MULTI:开启事务
EXEC:执行事务
DISCARD:取消事务
WATCH:监视事务中的键变化,一旦有改变则取消事务。
package main
import (
"github.com/garyburd/redigo/redis"
"fmt"
)
func main() {
conn,err := redis.Dial("tcp","10.1.210.69:6379")
if err != nil {
fmt.Println("connect redis error :",err)
return
}
defer conn.Close()
conn.Send("MULTI")
conn.Send("INCR", "foo")
conn.Send("INCR", "bar")
r, err := conn.Do("EXEC")
fmt.Println(r)
}
控制台打印结果:
[1, 1]