rename cache function from func() (interface{}, error) to func(ctx context.Context) (value interface{}, err error) for package gcache; add cache for function Tables of gdb.Core; improve Where condition with prefix handling for package gdb

This commit is contained in:
John Guo
2021-12-17 11:46:05 +08:00
parent f583f28953
commit b9d6ac26d1
15 changed files with 118 additions and 83 deletions

View File

@ -652,16 +652,26 @@ func (c *Core) writeSqlToLogger(ctx context.Context, sql *Sql) {
// HasTable determine whether the table name exists in the database.
func (c *Core) HasTable(name string) (bool, error) {
tableList, err := c.db.Tables(c.GetCtx())
result, err := c.GetCache().GetOrSetFunc(
c.GetCtx(),
fmt.Sprintf(`HasTable: %s`, name),
func(ctx context.Context) (interface{}, error) {
tableList, err := c.db.Tables(ctx)
if err != nil {
return false, err
}
for _, table := range tableList {
if table == name {
return true, nil
}
}
return false, nil
}, 0,
)
if err != nil {
return false, err
}
for _, table := range tableList {
if table == name {
return true, nil
}
}
return false, nil
return result.Bool(), nil
}
// isSoftCreatedFieldName checks and returns whether given filed name is an automatic-filled created time.

View File

@ -106,7 +106,7 @@ func (d *DriverMysql) Tables(ctx context.Context, schema ...string) (tables []st
return
}
// TableFields retrieves and returns the fields information of specified table of current
// TableFields retrieves and returns the fields' information of specified table of current
// schema.
//
// The parameter `link` is optional, if given nil it automatically retrieves a raw sql connection

View File

@ -87,7 +87,7 @@ func (d *DriverOracle) DoCommit(ctx context.Context, link Link, sql string, args
}()
var index int
// Convert place holder char '?' to string ":vx".
// Convert placeholder char '?' to string ":vx".
newSql, _ = gregex.ReplaceStringFunc("\\?", sql, func(s string) string {
index++
return fmt.Sprintf(":v%d", index)
@ -180,7 +180,7 @@ func (d *DriverOracle) Tables(ctx context.Context, schema ...string) (tables []s
return
}
// TableFields retrieves and returns the fields information of specified table of current schema.
// TableFields retrieves and returns the fields' information of specified table of current schema.
//
// Also see DriverMysql.TableFields.
func (d *DriverOracle) TableFields(ctx context.Context, table string, schema ...string) (fields map[string]*TableField, err error) {

View File

@ -404,7 +404,7 @@ type formatWhereHolderInput struct {
OmitNil bool
OmitEmpty bool
Schema string
Table string
Table string // Table is used for fields mapping and filtering internally.
Prefix string // Field prefix, eg: "user.", "order.".
}
@ -439,15 +439,15 @@ func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newAr
}
case reflect.Struct:
// If the `where` parameter is defined like `xxxForDao`, it then adds `OmitNil` option for this condition,
// If the `where` parameter is DTO struct, it then adds `OmitNil` option for this condition,
// which will filter all nil parameters in `where`.
if isDtoStruct(in.Where) {
in.OmitNil = true
}
// If `where` struct implements iIterator interface,
// If `where` struct implements `iIterator` interface,
// it then uses its Iterate function to iterate its key-value pairs.
// For example, ListMap and TreeMap are ordered map,
// which implement iIterator interface and are index-friendly for where conditions.
// which implement `iIterator` interface and are index-friendly for where conditions.
if iterator, ok := in.Where.(iIterator); ok {
iterator.Iterator(func(key, value interface{}) bool {
ketStr := gconv.String(key)
@ -478,6 +478,19 @@ func formatWhereHolder(db DB, in formatWhereHolderInput) (newWhere string, newAr
structField reflect.StructField
data = DataToMapDeep(in.Where)
)
// If `Prefix` is given, it checks and retrieves the table name.
if in.Prefix != "" {
hasTable, _ := db.GetCore().HasTable(in.Prefix)
if hasTable {
in.Table = in.Prefix
} else {
ormTagTableName := getTableNameFromOrmTag(in.Where)
if ormTagTableName != "" {
in.Table = ormTagTableName
}
}
}
// Mapping and filtering fields if `Table` is given.
if in.Table != "" {
data, _ = db.GetCore().mappingAndFilterData(in.Schema, in.Table, data, true)
}

View File

@ -600,11 +600,16 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
m.db.GetCore().guessPrimaryTableName(m.tablesInit),
)
}
var (
tableForMappingAndFiltering = m.tables
)
if len(m.whereHolder) > 0 {
for _, v := range m.whereHolder {
tableForMappingAndFiltering = m.tables
if v.Prefix == "" {
v.Prefix = autoPrefix
}
switch v.Operator {
case whereHolderOperatorWhere:
if conditionWhere == "" {
@ -614,7 +619,7 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
OmitNil: m.option&optionOmitNilWhere > 0,
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
Schema: m.schema,
Table: m.tables,
Table: tableForMappingAndFiltering,
Prefix: v.Prefix,
})
if len(newWhere) > 0 {
@ -632,7 +637,7 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
OmitNil: m.option&optionOmitNilWhere > 0,
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
Schema: m.schema,
Table: m.tables,
Table: tableForMappingAndFiltering,
Prefix: v.Prefix,
})
if len(newWhere) > 0 {
@ -653,7 +658,7 @@ func (m *Model) formatCondition(limit1 bool, isCountStatement bool) (conditionWh
OmitNil: m.option&optionOmitNilWhere > 0,
OmitEmpty: m.option&optionOmitEmptyWhere > 0,
Schema: m.schema,
Table: m.tables,
Table: tableForMappingAndFiltering,
Prefix: v.Prefix,
})
if len(newWhere) > 0 {

View File

@ -7,6 +7,7 @@
package ghttp
import (
"context"
"fmt"
"strings"
@ -53,13 +54,14 @@ func (s *Server) getHandlersWithCache(r *Request) (parsedItems []*handlerParsedI
value, err := s.serveCache.GetOrSetFunc(
ctx,
s.serveHandlerKey(method, r.URL.Path, r.GetHost()),
func() (interface{}, error) {
func(ctx context.Context) (interface{}, error) {
parsedItems, hasHook, hasServe = s.searchHandlers(method, r.URL.Path, r.GetHost())
if parsedItems != nil {
return &handlerCacheItem{parsedItems, hasHook, hasServe}, nil
}
return nil, nil
}, routeCacheDuration)
}, routeCacheDuration,
)
if err != nil {
intlog.Error(ctx, err)
}

View File

@ -16,6 +16,9 @@ import (
"github.com/gogf/gf/v2/container/gvar"
)
// Func is the cache function that calculates and returns the value.
type Func func(ctx context.Context) (value interface{}, err error)
// Default cache object.
var defaultCache = New()
@ -53,7 +56,7 @@ func SetIfNotExist(ctx context.Context, key interface{}, value interface{}, dura
//
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil.
func SetIfNotExistFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (bool, error) {
func SetIfNotExistFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) {
return defaultCache.SetIfNotExistFunc(ctx, key, f, duration)
}
@ -65,7 +68,7 @@ func SetIfNotExistFunc(ctx context.Context, key interface{}, f func() (interface
//
// Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func SetIfNotExistFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (bool, error) {
func SetIfNotExistFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) {
return defaultCache.SetIfNotExistFuncLock(ctx, key, f, duration)
}
@ -94,7 +97,7 @@ func GetOrSet(ctx context.Context, key interface{}, value interface{}, duration
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
// if `value` is a function and the function result is nil.
func GetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (*gvar.Var, error) {
func GetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) {
return defaultCache.GetOrSetFunc(ctx, key, f, duration)
}
@ -108,7 +111,7 @@ func GetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, e
//
// Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func GetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (*gvar.Var, error) {
func GetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) {
return defaultCache.GetOrSetFuncLock(ctx, key, f, duration)
}
@ -192,12 +195,12 @@ func MustGetOrSet(ctx context.Context, key interface{}, value interface{}, durat
}
// MustGetOrSetFunc acts like GetOrSetFunc, but it panics if any error occurs.
func MustGetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) *gvar.Var {
func MustGetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) *gvar.Var {
return defaultCache.MustGetOrSet(ctx, key, f, duration)
}
// MustGetOrSetFuncLock acts like GetOrSetFuncLock, but it panics if any error occurs.
func MustGetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) *gvar.Var {
func MustGetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) *gvar.Var {
return defaultCache.MustGetOrSetFuncLock(ctx, key, f, duration)
}

View File

@ -45,7 +45,7 @@ type Adapter interface {
//
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil.
SetIfNotExistFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (ok bool, err error)
SetIfNotExistFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (ok bool, err error)
// SetIfNotExistFuncLock sets `key` with result of function `f` and returns true
// if `key` does not exist in the cache, or else it does nothing and returns false if `key` already exists.
@ -55,7 +55,7 @@ type Adapter interface {
//
// Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
SetIfNotExistFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (ok bool, err error)
SetIfNotExistFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (ok bool, err error)
// Get retrieves and returns the associated value of given `key`.
// It returns nil if it does not exist, or its value is nil, or it's expired.
@ -78,7 +78,7 @@ type Adapter interface {
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
// if `value` is a function and the function result is nil.
GetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (result *gvar.Var, err error)
GetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (result *gvar.Var, err error)
// GetOrSetFuncLock retrieves and returns the value of `key`, or sets `key` with result of
// function `f` and returns its result if `key` does not exist in the cache. The key-value
@ -90,7 +90,7 @@ type Adapter interface {
//
// Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
GetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (result *gvar.Var, err error)
GetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (result *gvar.Var, err error)
// Contains checks and returns true if `key` exists in the cache, or else returns false.
Contains(ctx context.Context, key interface{}) (bool, error)

View File

@ -120,7 +120,7 @@ func (c *AdapterMemory) SetIfNotExist(ctx context.Context, key interface{}, valu
return false, err
}
if !isContained {
if _, err = c.doSetWithLockCheck(key, value, duration); err != nil {
if _, err = c.doSetWithLockCheck(ctx, key, value, duration); err != nil {
return false, err
}
return true, nil
@ -136,17 +136,17 @@ func (c *AdapterMemory) SetIfNotExist(ctx context.Context, key interface{}, valu
//
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil.
func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (bool, error) {
func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) {
isContained, err := c.Contains(ctx, key)
if err != nil {
return false, err
}
if !isContained {
value, err := f()
value, err := f(ctx)
if err != nil {
return false, err
}
if _, err = c.doSetWithLockCheck(key, value, duration); err != nil {
if _, err = c.doSetWithLockCheck(ctx, key, value, duration); err != nil {
return false, err
}
return true, nil
@ -162,13 +162,13 @@ func (c *AdapterMemory) SetIfNotExistFunc(ctx context.Context, key interface{},
//
// Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func (c *AdapterMemory) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (bool, error) {
func (c *AdapterMemory) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (bool, error) {
isContained, err := c.Contains(ctx, key)
if err != nil {
return false, err
}
if !isContained {
if _, err = c.doSetWithLockCheck(key, f, duration); err != nil {
if _, err = c.doSetWithLockCheck(ctx, key, f, duration); err != nil {
return false, err
}
return true, nil
@ -204,7 +204,7 @@ func (c *AdapterMemory) GetOrSet(ctx context.Context, key interface{}, value int
return nil, err
}
if v == nil {
return c.doSetWithLockCheck(key, value, duration)
return c.doSetWithLockCheck(ctx, key, value, duration)
} else {
return v, nil
}
@ -217,20 +217,20 @@ func (c *AdapterMemory) GetOrSet(ctx context.Context, key interface{}, value int
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
// if `value` is a function and the function result is nil.
func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (*gvar.Var, error) {
func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) {
v, err := c.Get(ctx, key)
if err != nil {
return nil, err
}
if v == nil {
value, err := f()
value, err := f(ctx)
if err != nil {
return nil, err
}
if value == nil {
return nil, nil
}
return c.doSetWithLockCheck(key, value, duration)
return c.doSetWithLockCheck(ctx, key, value, duration)
} else {
return v, nil
}
@ -246,13 +246,13 @@ func (c *AdapterMemory) GetOrSetFunc(ctx context.Context, key interface{}, f fun
//
// Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func (c *AdapterMemory) GetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (*gvar.Var, error) {
func (c *AdapterMemory) GetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (*gvar.Var, error) {
v, err := c.Get(ctx, key)
if err != nil {
return nil, err
}
if v == nil {
return c.doSetWithLockCheck(key, f, duration)
return c.doSetWithLockCheck(ctx, key, f, duration)
} else {
return v, nil
}
@ -369,9 +369,9 @@ func (c *AdapterMemory) Close(ctx context.Context) error {
//
// It doubly checks the `key` whether exists in the cache using mutex writing lock
// before setting it to the cache.
func (c *AdapterMemory) doSetWithLockCheck(key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
func (c *AdapterMemory) doSetWithLockCheck(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
expireTimestamp := c.getInternalExpire(duration)
v, err := c.data.SetWithLock(key, value, expireTimestamp)
v, err := c.data.SetWithLock(ctx, key, value, expireTimestamp)
c.eventList.PushBack(&adapterMemoryEvent{k: key, e: expireTimestamp})
return gvar.New(v), err
}

View File

@ -7,6 +7,7 @@
package gcache
import (
"context"
"sync"
"time"
@ -153,7 +154,7 @@ func (d *adapterMemoryData) Set(key interface{}, value adapterMemoryItem) {
d.mu.Unlock()
}
// Sets batch sets cache with key-value pairs by `data`, which is expired after `duration`.
// SetMap batch sets cache with key-value pairs by `data`, which is expired after `duration`.
//
// It does not expire if `duration` == 0.
// It deletes the keys of `data` if `duration` < 0 or given `value` is nil.
@ -169,14 +170,14 @@ func (d *adapterMemoryData) SetMap(data map[interface{}]interface{}, expireTime
return nil
}
func (d *adapterMemoryData) SetWithLock(key interface{}, value interface{}, expireTimestamp int64) (interface{}, error) {
func (d *adapterMemoryData) SetWithLock(ctx context.Context, key interface{}, value interface{}, expireTimestamp int64) (interface{}, error) {
d.mu.Lock()
defer d.mu.Unlock()
if v, ok := d.data[key]; ok && !v.IsExpired() {
return v.v, nil
}
if f, ok := value.(func() (interface{}, error)); ok {
v, err := f()
if f, ok := value.(Func); ok {
v, err := f(ctx)
if err != nil {
return nil, err
}

View File

@ -104,8 +104,8 @@ func (c *AdapterRedis) SetIfNotExist(ctx context.Context, key interface{}, value
err error
)
// Execute the function and retrieve the result.
if f, ok := value.(func() (interface{}, error)); ok {
value, err = f()
if f, ok := value.(Func); ok {
value, err = f(ctx)
if value == nil {
return false, err
}
@ -143,8 +143,8 @@ func (c *AdapterRedis) SetIfNotExist(ctx context.Context, key interface{}, value
//
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil.
func (c *AdapterRedis) SetIfNotExistFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (ok bool, err error) {
value, err := f()
func (c *AdapterRedis) SetIfNotExistFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (ok bool, err error) {
value, err := f(ctx)
if err != nil {
return false, err
}
@ -159,8 +159,8 @@ func (c *AdapterRedis) SetIfNotExistFunc(ctx context.Context, key interface{}, f
//
// Note that it differs from function `SetIfNotExistFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func (c *AdapterRedis) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (ok bool, err error) {
value, err := f()
func (c *AdapterRedis) SetIfNotExistFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (ok bool, err error) {
value, err := f(ctx)
if err != nil {
return false, err
}
@ -198,13 +198,13 @@ func (c *AdapterRedis) GetOrSet(ctx context.Context, key interface{}, value inte
// It does not expire if `duration` == 0.
// It deletes the `key` if `duration` < 0 or given `value` is nil, but it does nothing
// if `value` is a function and the function result is nil.
func (c *AdapterRedis) GetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (result *gvar.Var, err error) {
func (c *AdapterRedis) GetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) (result *gvar.Var, err error) {
v, err := c.Get(ctx, key)
if err != nil {
return nil, err
}
if v == nil {
value, err := f()
value, err := f(ctx)
if err != nil {
return nil, err
}
@ -227,7 +227,7 @@ func (c *AdapterRedis) GetOrSetFunc(ctx context.Context, key interface{}, f func
//
// Note that it differs from function `GetOrSetFunc` is that the function `f` is executed within
// writing mutex lock for concurrent safety purpose.
func (c *AdapterRedis) GetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) (result *gvar.Var, err error) {
func (c *AdapterRedis) GetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) (result *gvar.Var, err error) {
return c.GetOrSetFunc(ctx, key, f, duration)
}

View File

@ -32,7 +32,7 @@ func (c *Cache) MustGetOrSet(ctx context.Context, key interface{}, value interfa
}
// MustGetOrSetFunc acts like GetOrSetFunc, but it panics if any error occurs.
func (c *Cache) MustGetOrSetFunc(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) *gvar.Var {
func (c *Cache) MustGetOrSetFunc(ctx context.Context, key interface{}, f Func, duration time.Duration) *gvar.Var {
v, err := c.GetOrSetFunc(ctx, key, f, duration)
if err != nil {
panic(err)
@ -41,7 +41,7 @@ func (c *Cache) MustGetOrSetFunc(ctx context.Context, key interface{}, f func()
}
// MustGetOrSetFuncLock acts like GetOrSetFuncLock, but it panics if any error occurs.
func (c *Cache) MustGetOrSetFuncLock(ctx context.Context, key interface{}, f func() (interface{}, error), duration time.Duration) *gvar.Var {
func (c *Cache) MustGetOrSetFuncLock(ctx context.Context, key interface{}, f Func, duration time.Duration) *gvar.Var {
v, err := c.GetOrSetFuncLock(ctx, key, f, duration)
if err != nil {
panic(err)

View File

@ -1,6 +1,7 @@
package gcache_test
import (
"context"
"fmt"
"time"
@ -360,14 +361,14 @@ func ExampleCache_GetOrSetFunc() {
// GetOrSetFunc retrieves and returns the value of `key`, or sets `key` with result of function `f`
// and returns its result if `key` does not exist in the cache.
c.GetOrSetFunc(ctx, "k1", func() (interface{}, error) {
c.GetOrSetFunc(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "v1", nil
}, 10000*time.Millisecond)
v, _ := c.Get(ctx, "k1")
fmt.Println(v)
// If func returns nil, no action is taken
c.GetOrSetFunc(ctx, "k2", func() (interface{}, error) {
c.GetOrSetFunc(ctx, "k2", func(ctx context.Context) (value interface{}, err error) {
return nil, nil
}, 10000*time.Millisecond)
v1, _ := c.Get(ctx, "k2")
@ -384,14 +385,14 @@ func ExampleCache_GetOrSetFuncLock() {
c := gcache.New()
// Modify locking Note that the function `f` should be executed within writing mutex lock for concurrent safety purpose.
c.GetOrSetFuncLock(ctx, "k1", func() (interface{}, error) {
c.GetOrSetFuncLock(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "v1", nil
}, 0)
v, _ := c.Get(ctx, "k1")
fmt.Println(v)
// Modification failed
c.GetOrSetFuncLock(ctx, "k1", func() (interface{}, error) {
c.GetOrSetFuncLock(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "update v1", nil
}, 0)
v, _ = c.Get(ctx, "k1")
@ -528,13 +529,13 @@ func ExampleCache_MustGetOrSetFunc() {
c := gcache.New()
// MustGetOrSetFunc acts like GetOrSetFunc, but it panics if any error occurs.
c.MustGetOrSetFunc(ctx, "k1", func() (interface{}, error) {
c.MustGetOrSetFunc(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "v1", nil
}, 10000*time.Millisecond)
v := c.MustGet(ctx, "k1")
fmt.Println(v)
c.MustGetOrSetFunc(ctx, "k2", func() (interface{}, error) {
c.MustGetOrSetFunc(ctx, "k2", func(ctx context.Context) (value interface{}, err error) {
return nil, nil
}, 10000*time.Millisecond)
v1 := c.MustGet(ctx, "k2")
@ -552,14 +553,14 @@ func ExampleCache_MustGetOrSetFuncLock() {
c := gcache.New()
// MustGetOrSetFuncLock acts like GetOrSetFuncLock, but it panics if any error occurs.
c.MustGetOrSetFuncLock(ctx, "k1", func() (interface{}, error) {
c.MustGetOrSetFuncLock(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "v1", nil
}, 0)
v := c.MustGet(ctx, "k1")
fmt.Println(v)
// Modification failed
c.MustGetOrSetFuncLock(ctx, "k1", func() (interface{}, error) {
c.MustGetOrSetFuncLock(ctx, "k1", func(ctx context.Context) (value interface{}, err error) {
return "update v1", nil
}, 0)
v = c.MustGet(ctx, "k1")

View File

@ -238,7 +238,7 @@ func TestCache_SetIfNotExist(t *testing.T) {
func TestCache_SetIfNotExistFunc(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
exist, err := cache.SetIfNotExistFunc(ctx, 1, func() (interface{}, error) {
exist, err := cache.SetIfNotExistFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
t.AssertNil(err)
@ -247,7 +247,7 @@ func TestCache_SetIfNotExistFunc(t *testing.T) {
v, _ := cache.Get(ctx, 1)
t.Assert(v, 11)
exist, err = cache.SetIfNotExistFunc(ctx, 1, func() (interface{}, error) {
exist, err = cache.SetIfNotExistFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 22, nil
}, 0)
t.AssertNil(err)
@ -259,7 +259,7 @@ func TestCache_SetIfNotExistFunc(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
gcache.Remove(ctx, g.Slice{1, 2, 3}...)
ok, err := gcache.SetIfNotExistFunc(ctx, 1, func() (interface{}, error) {
ok, err := gcache.SetIfNotExistFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
t.AssertNil(err)
@ -268,7 +268,7 @@ func TestCache_SetIfNotExistFunc(t *testing.T) {
v, _ := gcache.Get(ctx, 1)
t.Assert(v, 11)
ok, err = gcache.SetIfNotExistFunc(ctx, 1, func() (interface{}, error) {
ok, err = gcache.SetIfNotExistFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 22, nil
}, 0)
t.AssertNil(err)
@ -282,7 +282,7 @@ func TestCache_SetIfNotExistFunc(t *testing.T) {
func TestCache_SetIfNotExistFuncLock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
exist, err := cache.SetIfNotExistFuncLock(ctx, 1, func() (interface{}, error) {
exist, err := cache.SetIfNotExistFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
t.AssertNil(err)
@ -291,7 +291,7 @@ func TestCache_SetIfNotExistFuncLock(t *testing.T) {
v, _ := cache.Get(ctx, 1)
t.Assert(v, 11)
exist, err = cache.SetIfNotExistFuncLock(ctx, 1, func() (interface{}, error) {
exist, err = cache.SetIfNotExistFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 22, nil
}, 0)
t.AssertNil(err)
@ -303,7 +303,7 @@ func TestCache_SetIfNotExistFuncLock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
gcache.Remove(ctx, g.Slice{1, 2, 3}...)
exist, err := gcache.SetIfNotExistFuncLock(ctx, 1, func() (interface{}, error) {
exist, err := gcache.SetIfNotExistFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
t.AssertNil(err)
@ -312,7 +312,7 @@ func TestCache_SetIfNotExistFuncLock(t *testing.T) {
v, _ := gcache.Get(ctx, 1)
t.Assert(v, 11)
exist, err = gcache.SetIfNotExistFuncLock(ctx, 1, func() (interface{}, error) {
exist, err = gcache.SetIfNotExistFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 22, nil
}, 0)
t.AssertNil(err)
@ -377,13 +377,13 @@ func TestCache_GetOrSet(t *testing.T) {
func TestCache_GetOrSetFunc(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
cache.GetOrSetFunc(ctx, 1, func() (interface{}, error) {
cache.GetOrSetFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
v, _ := cache.Get(ctx, 1)
t.Assert(v, 11)
cache.GetOrSetFunc(ctx, 1, func() (interface{}, error) {
cache.GetOrSetFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 111, nil
}, 0)
v, _ = cache.Get(ctx, 1)
@ -391,13 +391,13 @@ func TestCache_GetOrSetFunc(t *testing.T) {
gcache.Remove(ctx, g.Slice{1, 2, 3}...)
gcache.GetOrSetFunc(ctx, 1, func() (interface{}, error) {
gcache.GetOrSetFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
v, _ = cache.Get(ctx, 1)
t.Assert(v, 11)
gcache.GetOrSetFunc(ctx, 1, func() (interface{}, error) {
gcache.GetOrSetFunc(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 111, nil
}, 0)
v, _ = cache.Get(ctx, 1)
@ -408,26 +408,26 @@ func TestCache_GetOrSetFunc(t *testing.T) {
func TestCache_GetOrSetFuncLock(t *testing.T) {
gtest.C(t, func(t *gtest.T) {
cache := gcache.New()
cache.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) {
cache.GetOrSetFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
v, _ := cache.Get(ctx, 1)
t.Assert(v, 11)
cache.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) {
cache.GetOrSetFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 111, nil
}, 0)
v, _ = cache.Get(ctx, 1)
t.Assert(v, 11)
gcache.Remove(ctx, g.Slice{1, 2, 3}...)
gcache.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) {
gcache.GetOrSetFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 11, nil
}, 0)
v, _ = cache.Get(ctx, 1)
t.Assert(v, 11)
gcache.GetOrSetFuncLock(ctx, 1, func() (interface{}, error) {
gcache.GetOrSetFuncLock(ctx, 1, func(ctx context.Context) (value interface{}, err error) {
return 111, nil
}, 0)
v, _ = cache.Get(ctx, 1)

View File

@ -57,7 +57,7 @@ func GetBytesWithCache(path string, duration ...time.Duration) []byte {
if len(duration) > 0 {
expire = duration[0]
}
r, _ := internalCache.GetOrSetFuncLock(ctx, cacheKey, func() (interface{}, error) {
r, _ := internalCache.GetOrSetFuncLock(ctx, cacheKey, func(ctx context.Context) (interface{}, error) {
b := GetBytes(path)
if b != nil {
// Adding this `path` to gfsnotify,