gcache
gcache copied to clipboard
Increment operator
It would be great that instead of a Get+Set that there was an Increment operator, ideally goroutine safe.
Sorry for late reply. Thanks your advice. I'm planning to implement GetAndSet method which enables a such operation.
@bluele If you detail the spec you have in mind for that method, I'll be happy to implement it.
Thanks, @aaronwinter . Hmm... How about with the following design?
func (c *LRUCache) GetOrSet(key, value interface{}) (interface{}, error) {
v, err := c.get(key, false)
if err == KeyNotFoundError {
it, err := c.set(key, value)
return it.value, err
}
return v, err
}
Or is it better to give a function that returns a value rather than a value?
This seems potentially problematic to design because of the problem of dealing with interface{}
and then having to interpret those values as one of the numeric values. You could potentially have two Increment
methods, one for integers and one for floats that attempts to enforce int64
and float64
respectively.
https://github.com/patrickmn/go-cache/blob/master/cache.go#L182
// Increment an item of type int, int8, int16, int32, int64, uintptr, uint,
// uint8, uint32, or uint64, float32 or float64 by n. Returns an error if the
// item's value is not an integer, if it was not found, or if it is not
// possible to increment it by n. To retrieve the incremented value, use one
// of the specialized methods, e.g. IncrementInt64.
func (c *cache) Increment(k string, n int64) error {
c.mu.Lock()
v, found := c.items[k]
if !found || v.Expired() {
c.mu.Unlock()
return fmt.Errorf("Item %s not found", k)
}
switch v.Object.(type) {
case int:
v.Object = v.Object.(int) + int(n)
case int8:
v.Object = v.Object.(int8) + int8(n)
case int16:
v.Object = v.Object.(int16) + int16(n)
case int32:
v.Object = v.Object.(int32) + int32(n)
case int64:
v.Object = v.Object.(int64) + n
case uint:
v.Object = v.Object.(uint) + uint(n)
case uintptr:
v.Object = v.Object.(uintptr) + uintptr(n)
case uint8:
v.Object = v.Object.(uint8) + uint8(n)
case uint16:
v.Object = v.Object.(uint16) + uint16(n)
case uint32:
v.Object = v.Object.(uint32) + uint32(n)
case uint64:
v.Object = v.Object.(uint64) + uint64(n)
case float32:
v.Object = v.Object.(float32) + float32(n)
case float64:
v.Object = v.Object.(float64) + float64(n)
default:
c.mu.Unlock()
return fmt.Errorf("The value for %s is not an integer", k)
}
c.items[k] = v
c.mu.Unlock()
return nil
}
@sergerdn I think that's the best solution here that you posted above (at least until Go gets generic typing support).
@sergerdn I think that's the best solution here that you posted above (at least until Go gets generic typing support).
@jadbox Have a look another solution with code generators, it looks not bad too:
- https://github.com/zgoat/zcache/blob/master/gen.go
- https://github.com/zgoat/zcache/blob/master/incr.go
It supports decrement also.