diff --git a/g/os/gcache/gcache.go b/g/os/gcache/gcache.go index 6e3fa7e6e..8815b4da7 100644 --- a/g/os/gcache/gcache.go +++ b/g/os/gcache/gcache.go @@ -12,21 +12,21 @@ var cache = New() // Set sets cache with - pair, which is expired after milliseconds. // If <=0 means it does not expire. -func Set(key interface{}, value interface{}, expire int) { - cache.Set(key, value, expire) +func Set(key interface{}, value interface{}, duration interface{}) { + cache.Set(key, value, duration) } // SetIfNotExist sets cache with - pair if does not exist in the cache, // which is expired after milliseconds. // If <=0 means it does not expire. -func SetIfNotExist(key interface{}, value interface{}, expire int) bool { - return cache.SetIfNotExist(key, value, expire) +func SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool { + return cache.SetIfNotExist(key, value, duration) } // Sets batch sets cache with key-value pairs by , which is expired after milliseconds. // If <=0 means it does not expire. -func Sets(data map[interface{}]interface{}, expire int) { - cache.Sets(data, expire) +func Sets(data map[interface{}]interface{}, duration interface{}) { + cache.Sets(data, duration) } // Get returns the value of . @@ -39,8 +39,8 @@ func Get(key interface{}) interface{} { // or sets - pair and returns if does not exist in the cache. // The key-value pair expires after milliseconds. // If <=0 means it does not expire. -func GetOrSet(key interface{}, value interface{}, expire int) interface{} { - return cache.GetOrSet(key, value, expire) +func GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} { + return cache.GetOrSet(key, value, duration) } // GetOrSetFunc returns the value of , @@ -48,8 +48,8 @@ func GetOrSet(key interface{}, value interface{}, expire int) interface{} { // if does not exist in the cache. // The key-value pair expires after milliseconds. // If <=0 means it does not expire. -func GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{} { - return cache.GetOrSetFunc(key, f, expire) +func GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} { + return cache.GetOrSetFunc(key, f, duration) } // GetOrSetFuncLock returns the value of , @@ -59,8 +59,8 @@ func GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{} // If <=0 means it does not expire. // // Note that the function is executed within writing mutex lock. -func GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{} { - return cache.GetOrSetFuncLock(key, f, expire) +func GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} { + return cache.GetOrSetFuncLock(key, f, duration) } // Contains returns true if exists in the cache, or else returns false. diff --git a/g/os/gcache/gcache_mem_cache.go b/g/os/gcache/gcache_mem_cache.go index edb648c10..976d2c5a1 100644 --- a/g/os/gcache/gcache_mem_cache.go +++ b/g/os/gcache/gcache_mem_cache.go @@ -9,6 +9,7 @@ package gcache import ( "math" "sync" + "time" "github.com/gogf/gf/g/container/glist" "github.com/gogf/gf/g/container/gset" @@ -103,9 +104,21 @@ func (c *memCache) getOrNewExpireSet(expire int64) (expireSet *gset.Set) { return } +// getMilliExpire converts parameter to int type in milliseconds. +// +// Note that there's some performance cost in type assertion here, but it's valuable. +func (c *memCache) getMilliExpire(duration interface{}) int { + if d, ok := duration.(time.Duration); ok { + return int(d.Nanoseconds() / 1000000) + } else { + return duration.(int) + } +} + // Set sets cache with - pair, which is expired after milliseconds. // If <=0 means it does not expire. -func (c *memCache) Set(key interface{}, value interface{}, expire int) { +func (c *memCache) Set(key interface{}, value interface{}, duration interface{}) { + expire := c.getMilliExpire(duration) expireTime := c.getInternalExpire(expire) c.dataMu.Lock() c.data[key] = memCacheItem{v: value, e: expireTime} @@ -119,7 +132,8 @@ func (c *memCache) Set(key interface{}, value interface{}, expire int) { // // It doubly checks the whether exists in the cache using mutex writing lock // before setting it to the cache. -func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, expire int) interface{} { +func (c *memCache) doSetWithLockCheck(key interface{}, value interface{}, duration interface{}) interface{} { + expire := c.getMilliExpire(duration) expireTimestamp := c.getInternalExpire(expire) c.dataMu.Lock() defer c.dataMu.Unlock() @@ -149,7 +163,8 @@ func (c *memCache) getInternalExpire(expire int) int64 { // SetIfNotExist sets cache with - pair if does not exist in the cache, // which is expired after milliseconds. // If <=0 means it does not expire. -func (c *memCache) SetIfNotExist(key interface{}, value interface{}, expire int) bool { +func (c *memCache) SetIfNotExist(key interface{}, value interface{}, duration interface{}) bool { + expire := c.getMilliExpire(duration) if !c.Contains(key) { c.doSetWithLockCheck(key, value, expire) return true @@ -159,7 +174,8 @@ func (c *memCache) SetIfNotExist(key interface{}, value interface{}, expire int) // Sets batch sets cache with key-value pairs by , which is expired after milliseconds. // If <=0 means it does not expire. -func (c *memCache) Sets(data map[interface{}]interface{}, expire int) { +func (c *memCache) Sets(data map[interface{}]interface{}, duration interface{}) { + expire := c.getMilliExpire(duration) expireTime := c.getInternalExpire(expire) for k, v := range data { c.dataMu.Lock() @@ -189,9 +205,9 @@ func (c *memCache) Get(key interface{}) interface{} { // or sets - pair and returns if does not exist in the cache. // The key-value pair expires after milliseconds. // If <=0 means it does not expire. -func (c *memCache) GetOrSet(key interface{}, value interface{}, expire int) interface{} { +func (c *memCache) GetOrSet(key interface{}, value interface{}, duration interface{}) interface{} { if v := c.Get(key); v == nil { - return c.doSetWithLockCheck(key, value, expire) + return c.doSetWithLockCheck(key, value, duration) } else { return v } @@ -202,9 +218,9 @@ func (c *memCache) GetOrSet(key interface{}, value interface{}, expire int) inte // if does not exist in the cache. // The key-value pair expires after milliseconds. // If <=0 means it does not expire. -func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, expire int) interface{} { +func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, duration interface{}) interface{} { if v := c.Get(key); v == nil { - return c.doSetWithLockCheck(key, f(), expire) + return c.doSetWithLockCheck(key, f(), duration) } else { return v } @@ -217,9 +233,9 @@ func (c *memCache) GetOrSetFunc(key interface{}, f func() interface{}, expire in // If <=0 means it does not expire. // // Note that the function is executed within writing mutex lock. -func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, expire int) interface{} { +func (c *memCache) GetOrSetFuncLock(key interface{}, f func() interface{}, duration interface{}) interface{} { if v := c.Get(key); v == nil { - return c.doSetWithLockCheck(key, f, expire) + return c.doSetWithLockCheck(key, f, duration) } else { return v } diff --git a/g/os/gcache/gcache_z_unit_1_test.go b/g/os/gcache/gcache_z_unit_1_test.go index 0cd6ea07c..3c89dad8f 100644 --- a/g/os/gcache/gcache_z_unit_1_test.go +++ b/g/os/gcache/gcache_z_unit_1_test.go @@ -9,13 +9,14 @@ package gcache_test import ( + "testing" + "time" + "github.com/gogf/gf/g" "github.com/gogf/gf/g/container/gset" "github.com/gogf/gf/g/os/gcache" "github.com/gogf/gf/g/os/grpool" "github.com/gogf/gf/g/test/gtest" - "testing" - "time" ) //clear 用于清除全局缓存,因gcache api 暂未暴露 Clear 方法 @@ -49,6 +50,14 @@ func TestCache_Set_Expire(t *testing.T) { gtest.Assert(cache.Size(), 0) cache.Close() }) + + gtest.Case(t, func() { + cache := gcache.New() + cache.Set(1, 11, 100*time.Millisecond) + gtest.Assert(cache.Get(1), 11) + time.Sleep(200 * time.Millisecond) + gtest.Assert(cache.Get(1), nil) + }) } func TestCache_Keys_Values(t *testing.T) { @@ -205,7 +214,7 @@ func TestCache_SetConcurrency(t *testing.T) { }() select { case <-time.After(2 * time.Second): - t.Log("first part end") + //t.Log("first part end") } go func() { @@ -217,7 +226,7 @@ func TestCache_SetConcurrency(t *testing.T) { }() select { case <-time.After(2 * time.Second): - t.Log("second part end") + //t.Log("second part end") } }) }