实现缓存系统的CRUD接口
现在,我们可以为缓存系统实现CRUD接口了。我们可以使用以下接口向缓存系统添加数据:
// 设置缓存数据项,如果该项已存在则覆盖
func (c *Cache) Set(k string, v interface{}, d time.Duration) {
var e int64
if d == DefaultExpiration {
d = c.defaultExpiration
}
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
c.mu.Lock()
defer c.mu.Unlock()
c.items[k] = Item{
Object: v,
Expiration: e,
}
}
// 无锁操作设置数据项
func (c *Cache) set(k string, v interface{}, d time.Duration) {
var e int64
if d == DefaultExpiration {
d = c.defaultExpiration
}
if d > 0 {
e = time.Now().Add(d).UnixNano()
}
c.items[k] = Item{
Object: v,
Expiration: e,
}
}
// 获取数据项,还需要检查该项是否已过期
func (c *Cache) get(k string) (interface{}, bool) {
item, found := c.items[k]
if!found {
return nil, false
}
if item.Expired() {
return nil, false
}
return item.Object, true
}
// 添加数据项,如果该项已存在则返回错误
func (c *Cache) Add(k string, v interface{}, d time.Duration) error {
c.mu.Lock()
_, found := c.get(k)
if found {
c.mu.Unlock()
return fmt.Errorf("Item %s already exists", k)
}
c.set(k, v, d)
c.mu.Unlock()
return nil
}
// 获取数据项
func (c *Cache) Get(k string) (interface{}, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
item, found := c.items[k]
if!found {
return nil, false
}
if item.Expired() {
return nil, false
}
return item.Object, true
}
在上述代码中,我们实现了Set()
和Add()
接口。两者的主要区别在于,前者如果缓存系统中已存在数据项则覆盖它,而后者如果数据项已存在则抛出错误,防止缓存被错误覆盖。我们还实现了Get()
方法,用于从缓存系统中检索数据项。需要注意的是,缓存数据项存在的真正含义是该项存在且未过期。
接下来,我们可以实现删除和更新接口。
// 替换现有数据项
func (c *Cache) Replace(k string, v interface{}, d time.Duration) error {
c.mu.Lock()
_, found := c.get(k)
if!found {
c.mu.Unlock()
return fmt.Errorf("Item %s doesn't exist", k)
}
c.set(k, v, d)
c.mu.Unlock()
return nil
}
// 删除数据项
func (c *Cache) Delete(k string) {
c.mu.Lock()
c.delete(k)
c.mu.Unlock()
}
上述代码一目了然,所以我就不详细说明了。