// GetMulti returns several objects with only one trip to the cache. // The queried keys are the ones set in the out parameter. Any key present // in out and not found when querying the cache, will be deleted. The initial // values in the out map should be any value of the type which will be used // to decode the data for the given key. // e.g. Let's suppose our cache holds 3 objects: k1 of type []int, k2 of type // float64 and k3 of type string. To query for these 3 objects using GetMulti // you would initialze out like this: // // out := map[string]interface{}{ // k1: []int(nil), // k2: float(0), // k3: "", // } // err := c.GetMulti(out, nil) // // After the GetMulti() call, any keys not present in the cache will be // deleted from out, so len(out) will be <= 3 in this example. // // Alternatively, the second argument might be used to specify the types // of the object to be decoded. Users might implement their own Typer // or use UniTyper when requesting several objects of the same type. func (c *Cache) GetMulti(out map[string]interface{}, typer Typer) error { keys := make([]string, 0, len(out)) for k := range out { keys = append(keys, k) } if profile.On && profile.Profiling() { defer profile.Startf(cache, "GET MULTI", "%v", keys).End() } qkeys := keys if c.prefixLen > 0 { qkeys = make([]string, len(keys)) for ii, v := range keys { qkeys[ii] = c.backendKey(v) } } data, err := c.driver.GetMulti(qkeys) if err != nil { gerr := &cacheError{ op: "getting multiple keys", key: strings.Join(keys, ", "), err: err, } c.error(gerr) return gerr } if typer == nil { typer = mapTyper(out) } for ii, k := range keys { value := data[qkeys[ii]] if value == nil { delete(out, k) continue } typ := typer.Type(k) if typ == nil { derr := &cacheError{ op: "determining output type for object", key: k, err: fmt.Errorf("untyped value for key %q - please, set the value type like e.g. out[%q] = ([]int)(nil) or out[%q] = float64(0)", k, k, k), } c.error(derr) return derr } val := reflect.New(typ) err := c.codec.Decode(value, val.Interface()) if err != nil { derr := &cacheError{ op: "decoding object", key: k, err: err, } c.error(derr) return derr } out[k] = val.Elem().Interface() } return nil }
// Delete removes the key from the cache. An error is returned only // if the item was found but couldn't be deleted. Deleting a non-existant // item is always successful. func (c *Cache) Delete(key string) error { if profile.On { defer profile.Startf(cache, "DELETE %s", key).End() } err := c.driver.Delete(c.backendKey(key)) if err != nil { derr := &cacheError{ op: "deleting", key: key, err: err, } c.error(derr) return derr } return nil }