func TestContext(t *testing.T) { c, err := NewContext(nil) if err != nil { t.Fatalf("NewContext: %v", err) } defer c.Close() _, err = memcache.Get(c, "foo") if err != memcache.ErrCacheMiss { t.Fatalf("Get err = %v; want ErrCacheMiss", err) } it := &memcache.Item{ Key: "foo", Value: []byte("value"), } err = memcache.Set(c, it) if err != nil { t.Fatalf("Set err = %v", err) } it, err = memcache.Get(c, "foo") if err != nil { t.Fatalf("Get err = %v; want no error", err) } if string(it.Value) != "value" { t.Errorf("got Item.Value = %q; want %q", string(it.Value), "value") } e := &Entity{Foo: "foo", Bar: "bar"} k := datastore.NewKey(c, "Entity", "", 1, nil) _, err = datastore.Put(c, k, e) if err != nil { t.Fatalf("datastore.Put: %v", err) } }
func TestContext(t *testing.T) { c, err := NewContext(nil) if err != nil { t.Fatalf("NewContext: %v", err) } defer c.Close() _, err = memcache.Get(c, "foo") if err != memcache.ErrCacheMiss { t.Fatalf("Get err = %v; want ErrCacheMiss", err) } it := &memcache.Item{ Key: "foo", Value: []byte("value"), } err = memcache.Set(c, it) if err != nil { t.Fatalf("Set err = %v", err) } it, err = memcache.Get(c, "foo") if err != nil { t.Fatalf("Get err = %v; want no error", err) } if string(it.Value) != "value" { t.Errorf("got Item.Value = %q; want %q", string(it.Value), "value") } e := &Entity{Foo: "foo", Bar: "bar"} k := datastore.NewKey(c, "Entity", "", 1, nil) _, err = datastore.Put(c, k, e) if err != nil { t.Fatalf("datastore.Put: %v", err) } u := user.Current(c) if u != nil { t.Fatalf("User should not be not logged in!") } c.Login("*****@*****.**", false) u = user.Current(c) if u == nil { t.Fatalf("User should be logged in!") } id1 := u.ID c.Logout() u = user.Current(c) if u != nil { t.Fatalf("User should not be not logged in!") } c.Login("*****@*****.**", false) u = user.Current(c) if u == nil { t.Fatalf("User should be logged in!") } if id1 == u.ID { t.Fatalf("User IDs should be unique") } }
func Redirect(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) var dest Shortcut key := r.URL.Path if item, err := memcache.Get(c, key); err == nil { http.Redirect(w, r, string(item.Value), http.StatusSeeOther) return } else if err != memcache.ErrCacheMiss { c.Errorf("error getting item: %v", err) } dkey := datastore.NewKey(c, ShortcutType, key, 0, nil) if err := datastore.Get(c, dkey, &dest); err == datastore.ErrNoSuchEntity { c.Debugf("not found %q: %s", key, err) http.Error(w, "nothing to redirect", http.StatusNotFound) return } else if err != nil { c.Errorf("error: %s", err) http.Error(w, "ups...", http.StatusInternalServerError) return } item := memcache.Item{ Key: dest.ShortUrl, Value: []byte(dest.FullUrl), } if err := memcache.Set(c, &item); err != nil { c.Errorf("error setting item: %v", err) } http.Redirect(w, r, dest.FullUrl, http.StatusSeeOther) }
func searchsite(c *appengine.Context, referer string) int64 { hash := "ref:" + referer item, err := memcache.Get(*c, hash) if err != nil { q := datastore.NewQuery("MySite").Filter("url", referer) log.Print(q) /* t := q.Run(*c) /* var x MySite key, err := t.Next(&x) if err == datastore.Done { //Not found mysite := MySite { url: referer, created: datastore.SecondsToTime(time.Seconds()), views : 1, last_access: datastore.SecondsToTime(time.Seconds()), } key, _ := datastore.Put(*c, datastore.NewIncompleteKey("MySite"), &mysite) return key.IntID() } return key.IntID() */ return 0 } r, _ := strconv.Atoi64(string(item.Value)) return r }
func query(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) cacheKey := getCacheKey(c) if item, err := memcache.Get(c, cacheKey); err != memcache.ErrCacheMiss { fmt.Fprintf(w, "%s", item.Value) return } q := datastore.NewQuery("Entity") result := map[string]string{} for t := q.Run(c); ; { var entity Entity key, err := t.Next(&entity) if err == datastore.Done { break } if err != nil { result["error"] = fmt.Sprintf("%s", err) } keyString := fmt.Sprintf("%s", key) result[keyString] = entity.Value } jsonResult := mapToJson(result) item := &memcache.Item{ Key: cacheKey, Value: jsonResult, } memcache.Set(c, item) fmt.Fprintf(w, "%s", jsonResult) }
func cachePathTime(c appengine.Context, path string) (t int64, err error) { t, err = cacheTime(c) if err != nil { return 0, err } key := fmt.Sprintf("%d,mtime,%s", t, path) item, err := memcache.Get(c, key) if err == nil { v, err := strconv.ParseInt(string(item.Value), 10, 64) if err == nil { if chatty { c.Infof("cachePathTime %q = %v", key, v) } return v, nil } c.Criticalf("memcache.Get %q = %q (%v) - deleting", key, item.Value, err) memcache.Delete(c, key) } var seq int64 if fi, err := stat(c, path); err == nil { seq = fi.Seq } c.Infof("cachePathTime save %q = %v", key, seq) item = &memcache.Item{Key: key, Value: []byte(strconv.FormatInt(seq, 10))} if err := memcache.Set(c, item); err != nil { c.Criticalf("memcache.Set %q %q: %v", key, item.Value, err) } return seq, nil }
func RetrieveActDetails(c appengine.Context, actId int) (res *ActDetail, err os.Error) { var d DSActDetail if itm, err := memcache.Get(c, "actId__"+strconv.Itoa(actId)); err != nil && err != memcache.ErrCacheMiss { return nil, err } else if err == nil { // Cache hit buf := bytes.NewBuffer(itm.Value) dec := gob.NewDecoder(buf) dec.Decode(&d) } else { // Cache miss key := datastore.NewKey(c, "DSActDetail", "", int64(actId), nil) if err := datastore.Get(c, key, &d); err == datastore.ErrNoSuchEntity { return &ActDetail{ActId: actId}, nil } else if err != nil { return nil, err } buf := bytes.NewBufferString("") enc := gob.NewEncoder(buf) enc.Encode(d) itm := &memcache.Item{ Key: "actId__" + strconv.Itoa(actId), Value: buf.Bytes(), } err = memcache.Set(c, itm) c.Debugf("Request cache to memcache") } return d.fromDS(), nil }
func C1Logout(c appengine.Context) os.Error { u := user.Current(c).Email itm, err := memcache.Get(c, u+"__c1Sess") if err != nil && err != memcache.ErrCacheMiss { return err } if err == memcache.ErrCacheMiss { return nil } skey := string(itm.Value) session := c1SessionCookie(skey) r, err := http.NewRequest("GET", "https://www.cadetone.aafc.org.au/logout.php", nil) if err != nil { return err } injectSession(r, session) client := GetClient(c) _, err = client.Do(r) if err != nil { return err } memcache.Delete(c, u+"__c1Sess") return nil }
// Cached read rss func rssCachedGet(c appengine.Context, url string) ([]byte, error) { item, err := memcache.Get(c, url) if err != nil && err != memcache.ErrCacheMiss { return nil, err } // Cache hit if err == nil { return item.Value, err } // Cache miss channel, err := rssGet(c, url) if err != nil { return nil, err } buf := bytes.NewBuffer(nil) json.NewEncoder(buf).Encode(channel) expriation, err := time.ParseDuration("5m") if err != nil { return nil, err } item = &memcache.Item{ Key: url, Value: buf.Bytes(), Expiration: expriation, } return item.Value, memcache.Set(c, item) }
func cat(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) w.Header().Set("Content-Type", "application/json") switch r.Method { case "GET": var jsonResult []byte if item, err := memcache.Get(c, CAT); err == memcache.ErrCacheMiss { q := datastore.NewQuery("Package").Filter("Accepted =", true) var packages []*Package if _, err := q.GetAll(c, &packages); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } var categories Categories for _, pkg := range packages { if strings.TrimSpace(pkg.Category) != "" { categories = categories.Add(pkg.Category) } } if jsonResult, err = json.Marshal(categories); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } memcache.Add(c, &memcache.Item{Key: CAT, Value: jsonResult}) } else { jsonResult = item.Value } w.Write(jsonResult) } }
// Lista entidades func ListEnt(c appengine.Context, ent string) *[]Entidad { estados := make([]Entidad, 0, 32) if item, err := memcache.Get(c, "estados"); err == memcache.ErrCacheMiss { q := datastore.NewQuery("Entidad") if _, err := q.GetAll(c, &estados); err != nil { return nil } b, _ := json.Marshal(estados) item := &memcache.Item{ Key: "estados", Value: b, } if err := memcache.Add(c, item); err == memcache.ErrNotStored { c.Errorf("memcache.Add Entidad : %v", err) } } else { //c.Infof("Memcache activo: %v", item.Key) if err := json.Unmarshal(item.Value, &estados); err != nil { c.Errorf("Memcache Unmarshalling item: %v", err) } } for i, _ := range estados { if ent == estados[i].CveEnt { estados[i].Selected = `selected` } } return &estados }
func ListCat(c appengine.Context, IdCat int) *[]Categoria { var categorias []Categoria if item, err := memcache.Get(c, "categorias"); err == memcache.ErrCacheMiss { q := datastore.NewQuery("Categoria") //n, _ := q.Count(c) //cats := make([]Categoria, 0, n) if _, err := q.GetAll(c, &categorias); err != nil { return nil } b, _ := json.Marshal(categorias) item := &memcache.Item{ Key: "categorias", Value: b, } if err := memcache.Add(c, item); err == memcache.ErrNotStored { c.Errorf("memcache.Add Categoria : %v", err) } } else { c.Infof("Memcache activo: %v", item.Key) if err := json.Unmarshal(item.Value, &categorias); err != nil { c.Errorf("Memcache Unmarchalling item: %v", err) } } for i, _ := range categorias { if IdCat == categorias[i].IdCat { categorias[i].Selected = `selected` } } return &categorias }
func setServiceAccountForDev(c appengine.Context, s *Service) error { transport := &oauth.Transport{ Config: config, Transport: &urlfetch.Transport{ Context: c, }, } // cacheがあるか? item, err := memcache.Get(c, tokenCacheKey) if err == memcache.ErrCacheMiss { return fmt.Errorf("Visit this URL to get a code: http://localhost:8081/_admin/gapi_auth") } else if err != nil { return err } // トークンの読み込み token := &oauth.Token{} err = json.Unmarshal(item.Value, token) if err != nil { return err } // トークンの更新 transport.Token = token err = transport.Refresh() if err != nil { return err } client := transport.Client() service, err := bigquery.New(client) if err != nil { return err } s.bq = service return nil }
func (c Creature) Serve(response http.ResponseWriter, request *http.Request, ctx appengine.Context, width int, height int) { max := int(math.Max(float64(width), float64(height))) key := c.Name + ":" + strconv.Itoa(width) + "x" + strconv.Itoa(height) if width == 0 || height == 0 { http.NotFound(response, request) } // In cache? if cached, err := memcache.Get(ctx, key); err == nil { response.Header().Set("Content-Type", "image/jpeg") response.Write(cached.Value) return } if image, err := c.CropImage(width, height, max, ctx); err == nil { response.Header().Set("Content-Type", "image/jpeg") // Get the raw data and cache it writer := bytes.NewBuffer(make([]byte, 0)) jpeg.Encode(writer, image, nil) item := memcache.Item{ Key: key, Value: writer.Bytes(), } memcache.Set(ctx, &item) response.Write(item.Value) return } http.NotFound(response, request) }
func getReminderDate(c appengine.Context, text string) (time.Time, error) { re, err := regexp.Compile(`diaryentry\d+tag`) if err != nil { return time.Now(), fmt.Errorf("Failed to compile regex: %v", err) } tag := re.FindString(text) if tag == "" { return time.Now(), fmt.Errorf("Failed to match tag") } item, err := memcache.Get(c, tag) if err == memcache.ErrCacheMiss { return time.Now(), fmt.Errorf("item not in the cache") } else if err != nil { return time.Now(), fmt.Errorf("error getting item: %v", err) } date, err := time.Parse(time.RFC850, string(item.Value)) if err != nil { return time.Now(), fmt.Errorf("failed to parse date: %v", err) } return date, nil }
func loadHandler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) id, ok := parseIdParam(w, r) if !ok { return } // try memcache memId := jsonMemId(id) if item, err := memcache.Get(c, memId); err == nil { sendJson(c, w, item.Value) return } c.Debugf("cache miss for %v", memId) // try datastore m, ok := loadMovie(w, r, id) if !ok { return } data, err := json.Marshal(&m) if err != nil { c.Errorf("can't marshal JSON for movie %v: %v", id, err) http.Error(w, "can't encode movie", http.StatusBadRequest) return } cacheJson(c, id, data) sendJson(c, w, data) }
func freshen(c appengine.Context, key string) error { s, ok := Sources[key] if !ok { return fmt.Errorf("%q not found", key) } item, err := memcache.Get(c, key+"_fresh") if err == memcache.ErrCacheMiss { return fetch(c, key) } else if err != nil { return err } fresh, err := strconv.ParseInt(string(item.Value), 10, 64) if err != nil { return err } if time.Now().Unix() < fresh+int64(s.Refresh.Seconds()) { return nil } t := &taskqueue.Task{Path: "/fetch/" + key} if _, err := taskqueue.Add(c, t, "fetch-"+key); err != nil { return err } return nil }
func cachingGetUpstreamAtom(ctx appengine.Context) (*Feed, error) { item, err := memcache.Get(ctx, atomKey) if err != nil { ctx.Infof("making request to xkcd.com") feed, err := getUpstreamAtom(ctx) if err != nil { return nil, err } if b, err := xml.Marshal(feed); err == nil { item = &memcache.Item{ Key: atomKey, Value: b, Expiration: 5 * time.Minute, } memcache.Set(ctx, item) } return feed, nil } ctx.Infof("found feed in cache") var feed Feed if err := xml.Unmarshal(item.Value, &feed); err != nil { return nil, fmt.Errorf("failed to unmarshal cached feed: %v", err) } return &feed, nil }
// HTTP handler for /feed func feedHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Cache-control", config.Require("cache_control_header")) c := appengine.NewContext(r) key := r.URL.Path + "@" + appengine.VersionID(c) if item, err := memcache.Get(c, key); err == memcache.ErrCacheMiss { c.Infof("Page %s not in the cache", key) } else if err != nil { c.Errorf("error getting page: %v", err) } else { c.Infof("Page %s found in the cache", key) w.Write(item.Value) return } entry_count, _ := config.GetInt("entries_per_page") entries, _ := GetEntries(c, EntryQuery{IsPage: false, Count: int(entry_count)}) links := make([]SavedLink, 0) context, _ := GetTemplateContext(entries, links, "Atom Feed", "feed", r) var contentBuffer bytes.Buffer feedTpl.ExecuteTemplate(&contentBuffer, "feed.html", context) content, _ := ioutil.ReadAll(&contentBuffer) w.Write(content) // Feeds get cached infinitely, until an edit flushes it. storeInCache(c, key, content, 0) }
func getCached(c appengine.Context, key string, missing func(appengine.Context, string) (*bytes.Buffer, error)) (*memcache.Item, error) { item, err := memcache.Get(c, key) if err == memcache.ErrCacheMiss { c.Infof("item not in the cache: %v", key) result, err := missing(c, key) if err != nil { return nil, err } item = &memcache.Item{ Key: key, Value: result.Bytes(), } if err := memcache.Add(c, item); err == memcache.ErrNotStored { c.Warningf("item with key %q already exists", item.Key) } else if err != nil { return item, err } } else if err != nil { return item, err } else { c.Infof("Cache hit: %v", key) } return item, nil }
func updateCacheTime(c appengine.Context, seq int64) { const key = rootMemcacheKey bseq := []byte(strconv.FormatInt(seq, 10)) for tries := 0; tries < 10; tries++ { item, err := memcache.Get(c, key) if err != nil { c.Infof("memcache.Get %q: %v", key, err) err = memcache.Add(c, &memcache.Item{Key: key, Value: bseq}) if err == nil { c.Infof("memcache.Add %q %q ok", key, bseq) return } c.Infof("memcache.Add %q %q: %v", key, bseq, err) } v, err := strconv.ParseInt(string(item.Value), 10, 64) if err != nil { c.Criticalf("memcache.Get %q = %q (%v)", key, item.Value, err) return } if v >= seq { return } item.Value = bseq err = memcache.CompareAndSwap(c, item) if err == nil { c.Infof("memcache.CAS %q %d->%d ok", key, v, seq) return } c.Infof("memcache.CAS %q %d->%d: %v", key, v, seq, err) } c.Criticalf("repeatedly failed to update root key") }
func GetPage(r *http.Request, name string) (*Page, error) { var page *Page c := appengine.NewContext(r) if item, err := memcache.Get(c, "page"+name); err == memcache.ErrCacheMiss { // Fetch the page q := datastore.NewQuery("Page").Filter("Name =", name) var pages []*Page keys, err := q.GetAll(c, &pages) if err != nil { return nil, err } if keys == nil || pages == nil { return nil, errors.New(name + " page doesn't exit") } page = pages[0] } else { if err := json.Unmarshal(item.Value, &page); err != nil { return nil, err } } return page, nil }
func updateHandler(w http.ResponseWriter, r *http.Request) { c := gae.NewContext(r) g := goon.FromContext(c) if r.Header.Get("X-AppEngine-Cron") != "true" { http.NotFound(w, r) return } var ups []UpdateSchedule if cache, err := memcache.Get(c, "UpdateSchedule"); err == memcache.ErrCacheMiss { q := datastore.NewQuery("UpdateSchedule") if _, err := g.GetAll(q, &ups); err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } if val, err := serialize(&ups); err == nil { item := memcache.Item{Key: "UpdateSchedule", Value: val, Expiration: time.Hour * 12} memcache.Add(c, &item) } } else if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } else { deserialize(cache.Value, &ups) } now := time.Now() for _, us := range ups { if us.IsUpdateTime(now) { if err := updateVillage(us, g); err != nil { c.Debugf("%v", err) } memcache.Delete(c, "UpdateSchedule") } } return }
func view(prefix string) http.Handler { f := func(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) p := r.URL.Path[len(prefix):] if p == "" { p = "index" } s := new(Page) k := datastore.NewKey(c, "string", p, 0, nil) if item, err := memcache.Get(c, p); err == memcache.ErrCacheMiss { datastore.Get(c, k, s) err = memcache.Set(c, &memcache.Item{Key: p, Value: []byte(s.Content)}) if err != nil { panic(err) } } else if err != nil { panic(err) } else { s.Content = string(item.Value) } output := string(blackfriday.MarkdownCommon([]byte(s.Content))) viewTemplate.Execute(w, Foo{p, output, ""}) } return http.HandlerFunc(f) }
func get(w http.ResponseWriter, r *http.Request) { keyName := r.FormValue("key") c := appengine.NewContext(r) result := map[string]string{ keyName: "", "error": "", } if item, err := memcache.Get(c, keyName); err == nil { result[keyName] = fmt.Sprintf("%q", item.Value) fmt.Fprintf(w, "%s", mapToJson(result)) return } key := datastore.NewKey("Entity", keyName, 0, nil) entity := new(Entity) if err := datastore.Get(c, key, entity); err == nil { result[keyName] = entity.Value // Set the value to speed up future reads - errors here aren't // that bad, so don't worry about them item := &memcache.Item{ Key: keyName, Value: []byte(entity.Value), } memcache.Set(c, item) } else { result["error"] = fmt.Sprintf("%s", err) } fmt.Fprintf(w, "%s", mapToJson(result)) }
func municipios(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) _, ok := sess.IsSess(w, r, c) if ok { if item, err := memcache.Get(c, "msp_"+r.FormValue("CveEnt")); err == memcache.ErrCacheMiss { if entidad, err := model.GetEntidad(c, r.FormValue("CveEnt")); err == nil { if municipios, _ := entidad.GetMunicipios(c); err == nil { b, _ := json.Marshal(municipios) item := &memcache.Item{ Key: "msp_" + r.FormValue("CveEnt"), Value: b, } if err := memcache.Add(c, item); err == memcache.ErrNotStored { c.Infof("item with key %q already exists", item.Key) } else if err != nil { c.Errorf("Error memcache.Add Municipio : %v", err) } c.Infof("CveMun generado: %v", item.Key) htmlComboMuns(w, municipios, r.FormValue("CveMun")) } } } else { //c.Infof("Memcache activo: %v", item.Key) var municipios []model.Municipio if err := json.Unmarshal(item.Value, &municipios); err != nil { c.Errorf("error adding item: %v", err) } htmlComboMuns(w, &municipios, r.FormValue("CveMun")) } } return }
func handle(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) item, err := memcache.Get(c, r.URL.Path) if err != nil && err != memcache.ErrCacheMiss { serveError(c, w, err) return } n := 0 if err == nil { n, err = strconv.Atoi(string(item.Value)) if err != nil { serveError(c, w, err) return } } n++ item = &memcache.Item{ Key: r.URL.Path, Value: []byte(strconv.Itoa(n)), } err = memcache.Set(c, item) if err != nil { serveError(c, w, err) return } w.Header().Set("Content-Type", "text/plain") fmt.Fprintf(w, "%q has been visited %d times", r.URL.Path, n) }
func loadRev(c appengine.Context, uuid string, ch chan revRes) { rv := revRes{} if item, err := memcache.Get(c, "rev."+uuid); err == nil { rv.rev = string(item.Value) } if rv.rev == "" { req, err := http.NewRequest("HEAD", baseDBURL+uniqueDB+"/unique_"+uuid, nil) if err != nil { rv.err = err ch <- rv return } req.Header.Set("Authorization", authHeader) t := &urlfetch.Transport{Context: c} resp, err := t.RoundTrip(req) if err != nil { rv.err = err ch <- rv return } if resp.StatusCode == 200 { rv.rev = resp.Header.Get("etag") if len(rv.rev) > 1 { rv.rev = rv.rev[1 : len(rv.rev)-1] } } else { c.Infof("Got unfavorable response for key: %v", resp.Status) } } ch <- rv }
// tileHandler implements a tile renderer for use with the Google Maps JavaScript API. // See http://code.google.com/apis/maps/documentation/javascript/maptypes.html#ImageMapTypes func tileHandler(w http.ResponseWriter, r *http.Request) { c := appengine.NewContext(r) x, _ := strconv.Atoi(r.FormValue("x")) y, _ := strconv.Atoi(r.FormValue("y")) z, _ := strconv.Atoi(r.FormValue("z")) w.Header().Set("Content-Type", "image/png") // Try memcache first. key := fmt.Sprintf("mandelbrot:%d/%d/%d", x, y, z) if z < maxMemcacheLevel { if item, err := memcache.Get(c, key); err == nil { w.Write(item.Value) return } } b := render(x, y, z) if z < maxMemcacheLevel { memcache.Set(c, &memcache.Item{ Key: key, Value: b, Expiration: 3600, // TTL = 1 hour }) } w.Header().Set("Content-Length", strconv.Itoa(len(b))) w.Write(b) }
func GetBuriggies(c appengine.Context, count int) (buriggies []*Buriggie, err error) { var gg []*Buriggie var cacheKey = "buriggies.list." + strconv.Itoa(count) // Get the item from the memcache if item, err := memcache.Get(c, cacheKey); err == memcache.ErrCacheMiss { // cache miss.. ADD to cache q := datastore.NewQuery("Greeting").Order("-Date").Limit(count) _, err = q.GetAll(c, &gg) qjs, _ := json.Marshal(gg) cache_duration, _ := time.ParseDuration("1d") // Create an Item - cache for a day item := &memcache.Item{ Key: cacheKey, Value: qjs, Expiration: cache_duration, } if err := memcache.Add(c, item); err != nil { c.Errorf("error setting item: %v", err) } } else if err != nil { c.Errorf("error getting item: %v", err) } else { err = json.Unmarshal(item.Value, &gg) } return gg, err }