先看一下我們講到哪里了:
cache2go的源碼前面我們已經講完了cacheitem和cachetable的實現,今天cahce和examples會一起講完~
1、cache.go源碼
前面的代碼看完之后現在看cache.go就太簡單了,上代碼吧~
1var (
2 cache = make(map[string]*CacheTable)
3 mutex sync.RWMutex
4)
5
6// Cache returns the existing cache table with given name or creates a new one
7// if the table does not exist yet.
8//【表存在則返回表,表不存在的時候創建一個不包含items的空表,然后返回之】
9func Cache(table string) *CacheTable {
10 mutex.RLock()
11 //【注意cache的類型,這是一個用於存CacheTable的map】
12 t, ok := cache[table]
13 mutex.RUnlock()
14
15 if !ok {
16 mutex.Lock()
17 //【表不存在的時候需要創建一個空表,這時候做了一個二次檢查,為的是並發安全】
18 t, ok = cache[table]
19 // Double check whether the table exists or not.
20 if !ok {
21 t = &CacheTable{
22 name: table,
23 items: make(map[interface{}]*CacheItem),
24 }
25 cache[table] = t
26 }
27 mutex.Unlock()
28 }
29
30 return t
31}
2、example
如上圖,項目中還有一個examples目錄,大家肯定已經猜到了里面的內容了,沒錯,就是上面介紹的一堆代碼組成的緩存庫,怎么玩?
下面我們一個一個來看這3個示例吧~
1、callbacks.go
1func main() {
2 //【創建一個名為myCache的緩存表】
3 cache := cache2go.Cache("myCache")
4
5 // This callback will be triggered every time a new item
6 // gets added to the cache.
7 //【每次有新item被加入到這個緩存表的時候會被觸發的回調函數】
8 //【這個函數只做了一個輸出的動作】
9 cache.SetAddedItemCallback(func(entry *cache2go.CacheItem) {
10 fmt.Println("Added:", entry.Key(), entry.Data(), entry.CreatedOn())
11 })
12 // This callback will be triggered every time an item
13 // is about to be removed from the cache.
14 //【當一個item被刪除時被觸發執行的回調函數,同樣只有一個打印功能】
15 cache.SetAboutToDeleteItemCallback(func(entry *cache2go.CacheItem) {
16 fmt.Println("Deleting:", entry.Key(), entry.Data(), entry.CreatedOn())
17 })
18
19 // Caching a new item will execute the AddedItem callback.
20 //【緩存中添加一條記錄】
21 cache.Add("someKey", 0, "This is a test!")
22
23 // Let's retrieve the item from the cache
24 //【讀取剛才存入的數據】
25 res, err := cache.Value("someKey")
26 if err == nil {
27 fmt.Println("Found value in cache:", res.Data())
28 } else {
29 fmt.Println("Error retrieving value from cache:", err)
30 }
31
32 // Deleting the item will execute the AboutToDeleteItem callback.
33 //【刪除someKey對應的記錄】
34 cache.Delete("someKey")
35
36 // Caching a new item that expires in 3 seconds
37 //【添加設置了3s存活時間的記錄】
38 res = cache.Add("anotherKey", 3*time.Second, "This is another test")
39
40 // This callback will be triggered when the item is about to expire
41 //【一旦觸發了刪除操作就會調用到下面這個回調函數,在這里也就是3s到期時被執行
42 res.SetAboutToExpireCallback(func(key interface{}) {
43 fmt.Println("About to expire:", key.(string))
44 })
45
46 //【為了等上面的3s時間到】
47 time.Sleep(5 * time.Second)
48}
2、dataloader.go
1func main() {
2 cache := cache2go.Cache("myCache")
3
4 // The data loader gets called automatically whenever something
5 // tries to retrieve a non-existing key from the cache.
6 //【當從cache中訪問一個不存在的key時會觸發這個回調函數】
7 cache.SetDataLoader(func(key interface{}, args ...interface{}) *cache2go.CacheItem {
8 // Apply some clever loading logic here, e.g. read values for
9 // this key from database, network or file.
10 //【這里可以做一些機智的處理,比如說從數據庫,網絡或者文件中讀取數據,這當然也是緩存的意義】
11 //key.(string)是類型斷言,將interface{}類型的數據轉回到string類型
12 val := "This is a test with key " + key.(string)
13
14 // This helper method creates the cached item for us. Yay!
15 //【很棒,這樣就構造了一個value,然后構造出item】
16 item := cache2go.NewCacheItem(key, 0, val)
17 return item
18 })
19
20 // Let's retrieve a few auto-generated items from the cache.
21 //【試着檢索一些自動生成的items】
22 for i := 0; i < 10; i++ {
23 //【將i轉換為字符串,拼接成someKey_1的形式】
24 res, err := cache.Value("someKey_" + strconv.Itoa(i))
25 if err == nil {
26 fmt.Println("Found value in cache:", res.Data())
27 } else {
28 fmt.Println("Error retrieving value from cache:", err)
29 }
30 }
31}
3、mycachedapp.go
1// Keys & values in cache2go can be of arbitrary types, e.g. a struct.
2//【這個例子中要存儲的數據是如下結構體類型】
3type myStruct struct {
4 text string
5 moreData []byte
6}
7
8func main() {
9 // Accessing a new cache table for the first time will create it.
10 //【創建緩存表myCache】
11 cache := cache2go.Cache("myCache")
12
13 // We will put a new item in the cache. It will expire after
14 // not being accessed via Value(key) for more than 5 seconds.
15 //【構造一個數據】
16 val := myStruct{"This is a test!", []byte{}}
17 //【存入數據,設置存活時間為5s】
18 cache.Add("someKey", 5*time.Second, &val)
19
20 // Let's retrieve the item from the cache.
21 //【試着讀取】
22 res, err := cache.Value("someKey")
23 if err == nil {
24 fmt.Println("Found value in cache:", res.Data().(*myStruct).text)
25 } else {
26 fmt.Println("Error retrieving value from cache:", err)
27 }
28
29 // Wait for the item to expire in cache.
30 //【等待6s之后,明顯是該過期了】
31 time.Sleep(6 * time.Second)
32 res, err = cache.Value("someKey")
33 if err != nil {
34 fmt.Println("Item is not cached (anymore).")
35 }
36
37 // Add another item that never expires.
38 //【再存入一個永不過期的數據】
39 cache.Add("someKey", 0, &val)
40
41 // cache2go supports a few handy callbacks and loading mechanisms.
42 //【設置回調函數,刪除數據的時候被調用】
43 cache.SetAboutToDeleteItemCallback(func(e *cache2go.CacheItem) {
44 fmt.Println("Deleting:", e.Key(), e.Data().(*myStruct).text, e.CreatedOn())
45 })
46
47 // Remove the item from the cache.
48 //【手動執行刪除操作,當然,上面設置的函數將被調用】
49 cache.Delete("someKey")
50
51 // And wipe the entire cache table.
52 //【抹去整個cache中的數據】
53 cache.Flush()
54}
終於全部講完了~
如上,整個項目除了測試代碼外,實現邏輯部分全部分析完了,cache2go算是非常簡短的go開源項目了,很適合作為第一個讀源碼項目,下面要分析的groupcache也是和cache相關,但是相比cache2go要復雜很多,groupcache是大名鼎鼎的memcache的go語言版,我們下周開始分析!