import (
"database/sql"
"github.com/go-redis/redis/v8"
)

var (
Mysql *sql.DB
Redis *redis.Client
)

有兩種方式連接redis,一種是使用配置方式,一種是使用字符串的方式

使用配置方式,通過設(shè)置redis.Options?結(jié)構(gòu)體,可以對redis的連接信息進(jìn)行設(shè)置

package db

import (
"context"
"database/sql"
"fmt"
"github.com/go-redis/redis/v8"
_ "github.com/go-sql-driver/mysql"
"time"
)

func InitDB() *sql.DB {
dsn := fmt.Sprintf("%s:%s@(%s)/%s?charset=%s&parseTime=true&loc=Local",
"root", "123456", "127.0.0.1:3306", "gintest", "utf8")

if conn, err := sql.Open("mysql", dsn); err != nil {
panic(err.Error())
} else {
conn.SetConnMaxLifetime(7 * time.Second) //設(shè)置空閑時(shí)間,這個(gè)是比mysql 主動斷開的時(shí)候短
conn.SetMaxOpenConns(10)
conn.SetMaxIdleConns(10)
return conn
}
}

func InitRedis() *redis.Client {
rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
})
result := rdb.Ping(context.Background())
fmt.Println("redis ping:", result.Val())
if result.Val()!="PONG"{
// 連接有問題
return nil
}
return rdb
}

還有一種是字符串的方式

opt, err := redis.ParseURL("redis://<user>:<pass>@localhost:6379/<db>")
if err != nil {
panic(err)
}
rdb := redis.NewClient(opt)

個(gè)人還是比較喜歡用配置的方式,可以很直觀的看出來各種參數(shù)。

如果連接沒有問題,執(zhí)行Ping命令,會返回「PONG」?字符串,如果有問題,如redis命令連接有問題,則返回空字符串,可以根據(jù)這個(gè)返回值判斷是否正常連接上了redis服務(wù)器。

在main.go 中對Redis進(jìn)行賦值

func main() {
r := gin.Default()
global.Mysql = db.InitDB()
global.Redis = db.InitRedis()
r.Run(":8080")
}

連接池

為了減少頻繁的數(shù)據(jù)庫連接,推薦使用連接池,由go-redis來維護(hù)可用的連接,在初始化redis連接時(shí),使用PoolSize?參數(shù)來設(shè)置連接池大小。

rdb := redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password set
DB: 0, // use default DB
PoolSize: 10,
})

操作redis

redis.Client 內(nèi)置了很多操作方法,基本上可以滿足一般的使用,如操作字符串的Get,Set, SetNX等,操作hash的HSet等,基本上和redis-cli差不多,下面以普通的字符串為例

redisSET命令的返回值說明如下

從 Redis 2.6.12 版本開始, SET 命令只在設(shè)置操作成功完成時(shí)才返回 OK ;如果命令使用了 NX 或者 XX 選項(xiàng), 但是因?yàn)闂l件沒達(dá)到而造成設(shè)置操作未執(zhí)行, 那么命令將返回空批量回復(fù)(NULL Bulk Reply)。?

參考:http://redisdoc.com/string/set.html

在handler文件中編寫代碼

func (UserV1) RedisSet(c *gin.Context)  {
key := c.Query("key")
val := c.Query("val")
result, err := global.Redis.Set(c, key,val,0).Result()
fmt.Println("err:", err)
fmt.Println(result)
c.JSON(200, gin.H{"result": result})
}

在V8版本的goredis中,操作redis的命令都需要一個(gè)context參數(shù),這里可以傳*gin.Context,上面的函數(shù)如果沒有錯(cuò)誤,err為nil, result 為OK。

空值nil問題

當(dāng)redis返回為空的時(shí)候,如要查詢的key 不存在時(shí),或者命令執(zhí)行時(shí)返回的就是nil,

如果key不存在的時(shí)候,也可以判斷Result()返回的err是否等于redisl.Nil

func (UserV1) RedisGet(c *gin.Context)  {
key := c.Query("key")
result := global.Redis.Get(c, key)
res := make(map[string]string)
val, err := result.Result()
if err == redis.Nil{
res["msg"] = fmt.Sprintf("沒有key:%s ", key)
}else if err!= nil{
res["msg"] = err.Error()
}else{
res["msg"] = val
}
c.JSON(200, gin.H{"data": res})
}

命令的執(zhí)行結(jié)果有多種,有的是String, 有的bool,還有Scan類型的,具體還得看源碼, 如Get返回的是*StringCmd,它的Result() 方法返回 的是string, err,又如SetNX返回的就是*BoolCmd類型,它的Result() 方法返回的就是bool,err, 則這時(shí)就可以直接判斷了。

func (UserV1) RedisSet(c *gin.Context)  {
key := c.Query("key")
val := c.Query("val")
result, err := global.Redis.SetNX(c, key,val,0).Result()
fmt.Println(result, err, 111)
if err == redis.Nil{
c.JSON(200, gin.H{"result": "key:"+key+" 已經(jīng)存在"})
}else if err!=nil{
c.JSON(200, gin.H{"result": err})
}else{
if result{
c.JSON(200, gin.H{"result": "設(shè)置成功"})
}else{
c.JSON(200, gin.H{"result": "設(shè)置失敗"})
}
}
}

本文簡單的介紹了使用goredis連接redis并執(zhí)行一些set,get,之后會再介紹更高級的使用場景,如消息隊(duì)列,發(fā)布訂閱,pipeline, 事務(wù)等。

參考文章

golang操作redis/go-redis庫 [1]

go-redis文檔[2]

本文章轉(zhuǎn)載微信公眾號@序語程言

上一篇:

2024年值得考慮的最佳API報(bào)告工具

下一篇:

提高效率的十大API性能監(jiān)控工具
#你可能也喜歡這些API文章!

我們有何不同?

API服務(wù)商零注冊

多API并行試用

數(shù)據(jù)驅(qū)動選型,提升決策效率

查看全部API→
??

熱門場景實(shí)測,選對API

#AI文本生成大模型API

對比大模型API的內(nèi)容創(chuàng)意新穎性、情感共鳴力、商業(yè)轉(zhuǎn)化潛力

25個(gè)渠道
一鍵對比試用API 限時(shí)免費(fèi)

#AI深度推理大模型API

對比大模型API的邏輯推理準(zhǔn)確性、分析深度、可視化建議合理性

10個(gè)渠道
一鍵對比試用API 限時(shí)免費(fèi)