1. 程式人生 > >go開源專案學習--cache2go

go開源專案學習--cache2go

地址:https://github.com/muesli/cache2go
主要特點:
1、併發安全,使用RWMutex鎖來保證併發執行
2、可設定過期時間,過期自動刪除
3、可設定操作的回撥函式,如增加、刪除時的回撥函式

主要結構和關係為:
cache:map型別,快取器,根據設定的快取資料名稱來存取相應的快取表CacheTable
CacheTable:快取表,儲存一類資料的快取結構,結構裡的map維護了一個key到快取項的對映,定義如下:

type CacheTable struct {
    sync.RWMutex  //鎖,為了併發安全
    name string   //表名
    items map[interface{}]*CacheItem  //快取專案
    cleanupTimer *time.Timer  //定時器,檢查快取項是否超時
    cleanupInterval time.Duration   //下次檢查超時的時間間隔
    logger *log.Logger   //輸出使用的logger
    //訪問一個不存在的項時,會呼叫此函式生成新資料專案, 呼叫SetDataLoader進行設定
    loadData func(key interface{}, args ...interface{}) *CacheItem   
    addedItem func(item *CacheItem)  //增加新快取項時呼叫此函式,呼叫SetAddedItemCallback進行設定
    aboutToDeleteItem func(item *CacheItem)  //刪除快取項時呼叫此函式,呼叫SetAboutToDeleteItemCallback進行設定
}

CacheItem:快取項,儲存資料的結構,定義如下:

type CacheItem struct {
	sync.RWMutex  //讀寫鎖
	key interface{}  //快取項的key
	data interface{}  //快取項的value
	lifeSpan time.Duration  //資料的過期時間,為0則不過期
	createdOn time.Time  //資料的加入時間
	accessedOn time.Time  //上次訪問時間,根據此值和lifeSpan判斷是否過期
	accessCount int64  //訪問次數統計
	aboutToExpire func(key interface{})  //超時回撥函式
}

以下是自己測試寫的例子,測試了Foreach、SetDataLoader、SetLogger和超時處理:

package main

import (
	"fmt"
	"log"
	"os"
	"time"

	"github.com/muesli/cache2go"
)

type student struct {
	id    int
	name  string
	age   int
	score int
}

func main() {
	cache := cache2go.Cache("studentInfo")
	jack := &student{1, "jack", 12, 90}
	tom := &student{2, "tom", 13, 65}
	tony := &student{3, "tony", 12, 80}
	saveTime := 5 * time.Second
	cache.Add(1, saveTime, jack)
	cache.Add(2, saveTime, tom)
	cache.Add(3, saveTime, tony)
	fmt.Println("students num:", cache.Count())

	printFunc := func(key interface{}, stu *cache2go.CacheItem) {
		fmt.Println(key, stu.Data())
	}
	cache.Foreach(printFunc)

	loadFunc := func(key interface{}, args ...interface{}) *cache2go.CacheItem {
		ftmp := &student{key.(int), "", 0, 0}
		item := cache2go.NewCacheItem(key, 0, ftmp)
		return item
	}
	cache.SetDataLoader(loadFunc)
	tmp, ok := cache.Value(4)
	if ok == nil {
		fmt.Println(tmp.Data())
	}
	logFile, err := os.Create("./log.txt")
	if err != nil {
		fmt.Println(err)
	}
	defer logFile.Close()
	logger := log.New(logFile, "mytest_", log.Ldate|log.Ltime|log.Lshortfile)
	logger.Println("this is test line")
	cache.SetLogger(logger)
	time.Sleep(7 * time.Second)
}

輸出結果:

students num: 3
1 &{1 jack 12 90}
2 &{2 tom 13 65}
3 &{3 tony 12 80}
&{4  0 0}

日誌列印結果:

mytest_2018/12/31 09:52:51 mytest.go:51: this is test line
mytest_2018/12/31 09:52:56 cachetable.go:330: Expiration check triggered after 5s for table studentInfo
mytest_2018/12/31 09:52:56 cachetable.go:330: Deleting item with key 1 created on 2018-12-31 09:52:51.7731682 +0800 CST m=+0.014991301 and hit 0 times from table studentInfo
mytest_2018/12/31 09:52:56 cachetable.go:330: Deleting item with key 2 created on 2018-12-31 09:52:51.7731682 +0800 CST m=+0.014991301 and hit 0 times from table studentInfo
mytest_2018/12/31 09:52:56 cachetable.go:330: Deleting item with key 3 created on 2018-12-31 09:52:51.7731682 +0800 CST m=+0.014991301 and hit 0 times from table studentInfo