I am toying with GAE, Go and the datastore. I have the following structs:
type Coinflip struct {
Participants []*datastore.Key
Head string
Tail string
Done bool
}
type Participant struct {
Email string
Seen datastore.Time
}
(For those wondering I store Participants
as a slice off Key
pointers because Go doesn't automatically dereferences entities.)
Now I want to find a Participant
with a particular Email
address associated with a know Coinflip
. Like so (this works):
coinflip, _ := find(key_as_string, context)
participants, _ := coinflip.fetchParticipants(context) /* a slice of Participant*/
var found *Participant
for i := 0; i < len(participants) && found == nil; i++ {
if participants[i].Email == r.FormValue("email") {
found = &participants[i]
}
}
(*found).Seen = datastore.SecondsToTime(time.Seconds())
How do I save *found
to the datastore? I need the key apparently but the coupling between the Participant
struct and the Key
is very loose.
I'm unsure how to proceed from here. Do I need to return the keys as well from the fetchParticipants
call? The Java and Python GAE implementation seem quite a bit simpler (just call put()
on the object).
Thanks in advance,
For interacting with data in Go
, consider using our new library https://github.com/matryer/gae-records for an Active Record, data objects wrapper around the datastore. It sorts out a lot of the hassle for you.
For example, it supports:
// create a new model for 'People'
People := gaerecords.NewModel("People")
// create a new person
mat := People.New()
mat.
SetString("name", "Mat")
SetInt64("age", 28)
.Put()
// load person with ID 1
person, _ := People.Find(1)
// change some fields
person.SetInt64("age", 29).Put()
// load all People
peeps, _ := People.FindAll()
// delete mat
mat.Delete()
// delete user with ID 2
People.Delete(2)
// find the first three People by passing a func(*datastore.Query)
// to the FindByQuery method
firstThree, _ := People.FindByQuery(func(q *datastore.Query){
q.Limit(3)
})
// build your own query and use that
var ageQuery *datastore.Query = People.NewQuery().
Limit(3).Order("-age")
// use FindByQuery with a query object
oldestThreePeople, _ := People.FindByQuery(ageQuery)
// using events, make sure 'People' records always get
// an 'updatedAt' value set before being put (created and updated)
People.BeforePut.On(func(c *gaerecords.EventContext){
person := c.Args[0].(*Record)
person.SetTime("updatedAt", datastore.SecondsToTime(time.Seconds()))
})
Do I need to return the keys as well from the fetchParticipants call?
Yes. And then call "func Put(c appengine.Context, key *Key, src interface{}) (*Key, os.Error)"
The Java and Python GAE implementation seem quite a bit simpler (just call put() on the object).
Probably a fair statement. The Go community has a very strong bias against "magic". In this case the Participant struct has two fields that you have declared. Adding the key to it in the background would be considered magic.