目錄
- 一、需求
- 二、實(shí)現(xiàn)連接Mysql并執(zhí)行查詢語句
- 三、寫一個(gè)錯(cuò)誤處理函數(shù)
- 四、設(shè)置二級(jí)緩存
一、需求
- 實(shí)現(xiàn)二級(jí)緩存
- 程序運(yùn)行起來后提示:“請(qǐng)輸入命令:”,如果輸入getall,查詢并顯示所有人員的信息
- 第一次時(shí)查詢mysql并將結(jié)果緩存在redis,設(shè)置60秒的過期時(shí)間
- 以后的每次查詢,如果redis有數(shù)據(jù)就從redis加載,沒有則重復(fù)上一步的操作
二、實(shí)現(xiàn)連接Mysql并執(zhí)行查詢語句
先實(shí)現(xiàn)需求二,當(dāng)輸入命令getall時(shí),查詢并顯示所有人員的信息。
package main
import (
"fmt"
_"github.com/go-sql-driver/mysql"
"github.com/jmoiron/sqlx"
)
type Human struct {
Name string `db:"name"`
Age int `db:"age"`
}
func main() {
var cmd string
for{
fmt.Println("請(qǐng)輸入命令:")
fmt.Scan(cmd)
switch cmd{
case "getall":
//顯示所有人的信息
GetAllPeople()
case "exit":
//退出程序
goto GAMEOVER
default:
fmt.Println("輸入的命令有誤,請(qǐng)重新輸入!")
}
}
GAMEOVER:
fmt.Println("GAME OVER")
}
func GetAllPeople() {
fmt.Println("allPeople")
//先嘗試拿緩存
GetPeopleFromRedis()
db, _ := sqlx.Connect("mysql", "root:123456@tcp(localhost:3306)/mydb")
defer db.Close()
var people []Human
err := db.Select(people, "select name,age from person")
if err!=nil{
fmt.Println("查詢失敗!err=",err)
}
fmt.Println(people)
CachePeople2Redis(people)
}
第一步還是導(dǎo)包,需要在mysql驅(qū)動(dòng)包前面加上下劃線_,因?yàn)樗皇且粋€(gè)驅(qū)動(dòng)文件,并不需要在代碼中調(diào)用它的有關(guān)API接口.
接下來的這個(gè)結(jié)構(gòu)體中后面的db:"name" db:"age"一定要加反單引號(hào),否則運(yùn)行時(shí)會(huì)報(bào)錯(cuò)。(傻傻的編者剛開始這里就出現(xiàn)問題啦~)
type Human struct {
Name string `db:"name"`
Age int `db:"age"`
}
然后main函數(shù)里面都是一些基本語法知識(shí),用了switch和goto這兩個(gè)內(nèi)容。
接下來就是連接數(shù)據(jù)庫了,這里要用到數(shù)據(jù)庫擴(kuò)展包Sqlx,Sqlx包其實(shí)最大最大的優(yōu)點(diǎn)是在查詢方面,也就是使用select時(shí)優(yōu)化得比較好。比原來的使用查詢方便了不止一點(diǎn)。
db, _ := sqlx.Connect("mysql", "root:123456@tcp(localhost:3306)/mydb")
driverName:mysql,表示驅(qū)動(dòng)器的名稱是mysql也就上面"github.com/go-sql-driver/mysql"導(dǎo)入的驅(qū)動(dòng)器。
dataSourceName是root:123456@tcp(localhost:3306)/mydb 它的含義是 賬戶名:密碼@tcp(ip:端口)/數(shù)據(jù)庫名稱。
將緩存查詢結(jié)果到Redis,就是通過這個(gè)函數(shù)CachePeople2Redis(people)。
三、寫一個(gè)錯(cuò)誤處理函數(shù)
func HandleError(err error,why string) {
if err != nil{
fmt.Println(err,why)
os.Exit(1)
}
}
因?yàn)楹竺嫘枰幚砗芏噱e(cuò)誤,而錯(cuò)誤處理也是GO的一個(gè)特性,所以我們這先寫一個(gè)錯(cuò)誤處理函數(shù)。
四、設(shè)置二級(jí)緩存
func CachePeople2Redis(people []Human) {
conn, _ := redis.Dial("tcp", "localhost:6379")
defer conn.Close()
for _,human := range people{
humanStr := fmt.Sprint(human)
_, err := conn.Do("rpush", "people", humanStr)
if err != nil{
fmt.Println("緩存失敗(rpush people),err=",err)
return
}
}
_, err := conn.Do("expire", "people", 66)
if err!=nil{
HandleError(err,"@expire people 60")
}
fmt.Println("緩存成功!")
}
redis.Dial()這個(gè)函數(shù)是用來連接redis的,需要給定網(wǎng)絡(luò)協(xié)議和IP地址及端口號(hào),redis的端口號(hào)默認(rèn)為6379.
defer conn.Close()表示延時(shí)結(jié)束與redis的連接,為了節(jié)省系統(tǒng)的io資源,需要及時(shí)關(guān)閉連接!剛?cè)腴T時(shí)我們很容易忘記這個(gè),需要我們養(yǎng)成習(xí)慣!
conn.Do()是用來執(zhí)行數(shù)據(jù)庫命令的,第一個(gè)參數(shù)是命令名,后面的參數(shù)是數(shù)據(jù)庫命令的參數(shù)。它返回的結(jié)果中reply是字節(jié)數(shù)組[]byte類型,需要根據(jù)具體的業(yè)務(wù)類型進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換。
這段代碼先將people數(shù)組中的每一個(gè)human放入到redis的people列表中。然后再執(zhí)行expire命令,將列表設(shè)置過期時(shí)間。
執(zhí)行成功!下面是運(yùn)行結(jié)果:
請(qǐng)輸入命令:
getall
allPeople
[{大揚(yáng) 21} {小飛 21} {大紅袍 1} {小芳 18}]
緩存成功!
請(qǐng)輸入命令:
然后去看看數(shù)據(jù)庫里面存進(jìn)去沒有。
127.0.0.1:6379> lrange people 0 -1
1) "{\xe5\xa4\xa7\xe6\x89\xac 21}"
2) "{\xe5\xb0\x8f\xe9\xa3\x9e 21}"
3) "{\xe5\xa4\xa7\xe7\xba\xa2\xe8\xa2\x8d 1}"
4) "{\xe5\xb0\x8f\xe8\x8a\xb3 18}"
過了一分鐘之后,再查看redis數(shù)據(jù)庫內(nèi)的數(shù)據(jù)。
127.0.0.1:6379> lrange people 0 -1
(empty list or set)
已經(jīng)消失了。
再寫一個(gè)函數(shù):
func GetPeopleFromRedis() (peopleStrs []string) {
//連數(shù)據(jù)庫
conn, _ := redis.Dial("tcp", "localhost:6379")
//延遲關(guān)閉
defer conn.Close()
//執(zhí)行命令
reply, err := conn.Do("lrange", "people", 0, -1)
//處理錯(cuò)誤
HandleError(err,"@lrange people 0 -1")
//類型轉(zhuǎn)換
peopleStrs, err = redis.Strings(reply, err)
//打印結(jié)果
fmt.Println("緩存拿取結(jié)果:",peopleStrs,err)
return
}
如果redis里面有就不需要從mysql里面取數(shù)據(jù)了。直接從redis里面利用lrange命令來獲取people的所有值。
到此這篇關(guān)于Go應(yīng)該如何實(shí)現(xiàn)二級(jí)緩存的文章就介紹到這了,更多相關(guān)Go 二級(jí)緩存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
您可能感興趣的文章:- Django如何實(shí)現(xiàn)內(nèi)容緩存示例詳解
- redis之django-redis的簡單緩存使用
- django緩存配置的幾種方法詳解
- 詳解Django框架中的視圖級(jí)緩存
- 詳解Django緩存處理中Vary頭部的使用
- Django中提供的6種緩存方式詳解
- react+django清除瀏覽器緩存的幾種方法小結(jié)
- golang實(shí)現(xiàn)LRU緩存淘汰算法的示例代碼
- Django頁面數(shù)據(jù)的緩存與使用的具體方法