Google Go不能生成唯一标识符吗?

huangapple go评论75阅读模式
英文:

Google Go not generating unique identifiers?

问题

我正在尝试持久化实体,并允许数据库生成一个键。不幸的是,我似乎无法从API中获取一个合成的ID...这是我正在做的事情:

case "POST":
    d,_ := ioutil.ReadAll( r.Body)
    participant := new(Participant)
    err := json.Unmarshal( d, &participant)
    if err != nil {
        serveError( c, w, err)
        return
    }

    var key *datastore.Key;
    if participant.ID == 0 {
        // 没有ID...创建一个不完整的键,让数据库创建一个
        key = datastore.NewIncompleteKey( c, "participant", parentKey)
    } else {
        // 有一个ID,使用它来更新
        key = datastore.NewKey( c, "participant", "", participant.ID, parentKey)
    }
    // 持久化!
    putKey, e := datastore.Put( c, key, participant)
    if e != nil {
         serveError( c, w, e)
         return
    }

    // 从数据库中获取,可能有新的ID
    if e = datastore.Get( c, putKey, participant); e != nil {
         serveError( c, w, e)
         return
    }

    // 发送给消费者
    json,_ := json.Marshal( participant)
    w.Write( json)

奇怪的是,ID总是为零!详细信息已持久化,但我得到了多个具有相同ID字段的持久化值。为了好玩,这是对象定义:

type Participant struct {
    ID         int64
    LastName   string
    FirstName  string
    Birthdate  string
    Email      string
    Cell       string
}

在进行GET操作后,我会得到一个实体列表(是的,我创建的实体,每次创建都有)都具有零ID。

[
 {"ID":0,"LastName":"Schmuck","FirstName":"Joe","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""}
]

为了完整起见,我还尝试使用ID值为零的NewKey(),但结果是相同的。关于NewKey的API文档中提到,(字符串)名称和ID都为零会创建一个不完整的键 - 我不知道如何使字符串为零,但nil不起作用。

有人帮我弄清楚这在文档的正确部分指向后可能是非常明显的事情。

英文:

I'm trying to persist entities, and allow the database to generate a key. Unfortunately, I can't seem to tease a synthetic ID out of the API... Here's what I'm doing:

case "POST":
    d,_ := ioutil.ReadAll( r.Body)
    participant := new(Participant)
    err := json.Unmarshal( d, &participant)
    if err != nil {
        serveError( c, w, err)
        return
    }

    var key *datastore.Key;
    if participant.ID == 0 {
        // no id yet .. create an incomplete key and allow the db to create one.
        key = datastore.NewIncompleteKey( c, "participant", parentKey)
    } else {
        // we have an id.  use that to update
        key = datastore.NewKey( c, "participant", "", participant.ID, parentKey)
    }
    // PERSIST!
    putKey, e := datastore.Put( c, key, participant)
    if e != nil {
         serveError( c, w, e)
         return
    }

    // Fetch back out of the database, presumably with my new ID
    if e = datastore.Get( c, putKey, participant); e != nil {
         serveError( c, w, e)
         return
    }

    // send to the consumer
    json,_ := json.Marshal( participant)
    w.Write( json)

Well, oddly enough the ID is always zero! The details are persisted, but I get multiple values persisted with the same ID field. For grins, here's the object definition:

type Participant struct {
    ID         int64
    LastName   string
    FirstName  string
    Birthdate  string
    Email      string
    Cell       string
}

Following up with a GET operation, I am presented a list of entities (yes, the entities I created, as many times as I created them) all with the ID of zero.

[
 {"ID":0,"LastName":"Schmuck","FirstName":"Joe","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""},
 {"ID":0,"LastName":"Schmuck","FirstName":"Jane","Birthdate":"12-12-12","Email":"","Cell":""}
]

For completeness, I've also tried using the NewKey() with an ID value of zero, but that was giving the same result. The API documentation about NewKey says something about the (string) name and ID both being zero creating an incomplete key -- I'm not sure how to make a string zero, but nil doesn't work.

Somebody help me figure out what is probably amazingly obvious once pointed to the correct section of the document.

答案1

得分: 5

我没有看到你在任何地方填充ID字段,所以当然它会是0,因为这是该字段的零值。当AppEngine存储它时,它不会修改你的结构体。当使用不完整的键时,你在Put结构体时得到的新创建的键包含生成的IntId()。我认为你的困惑是因为假设了文档从未提到的事情。也就是说,AppEngine会自动为你存储的数据自动填充ID字段。

由于在你的情况下,你希望结构体的ID字段存储在键中使用的ID,所以你可能希望在创建键时生成自己的唯一ID,而不是使用不完整的键。

当文档说一个字符串可以是零时,它指的是字符串类型的零值,即空字符串""。你可以在这里阅读更多关于零值的信息:http://golang.org/ref/spec#The_zero_value

英文:

I don't see you populate the ID field anywhere so of course it's going to be 0 since that's the zero value for that field. AppEngine won't modify your struct when it stores it. The newly created key you get back when you Put the struct contains the generated IntId() when an incomplete key is used. I think your confusion was caused by assuming something the docs never said. Namely that AppEngine would auto-populate ID fields in your stored data for you.

Since in your case you want the ID field of the struct to store the id used in the key you probably want to generate you're own unique ids for when you create a Key instead of using incomplete keys.

When the doc says a string can be zero it's referring to the zero value of a string type which would the empty string "". You can read more about zero values here: http://golang.org/ref/spec#The_zero_value

答案2

得分: 2

我看不到你在Put之前实际改变ID的值的地方。据我所知,它总是为0。我本来希望看到类似这样的代码:

// 持久化!
putKey, e := datastore.Put(c, key, participant)
if e != nil {
    // ...
}
// ...
participant.ID = putKey.IntID()
putKey, e = datastore.Put(c, putKey, participant)

没有经过测试,但你可以理解我的意思...否则ID将始终为0。

英文:

I don't see where you actually change the value of ID prior to the Put? As far as I can tell, it's always going to be 0. I would have expected to see something like:

// PERSIST!
putKey, e := datastore.Put( c, key, participant)
if e != nil {
    // ...
}
// ...
participant.ID = putKey.IntID()
putKey, e = datastore.Put(c, putKey, participant)

Not tested, but you get the picture... otherwise ID will always be 0.

huangapple
  • 本文由 发表于 2013年1月4日 14:08:08
  • 转载请务必保留本文链接:https://go.coder-hub.com/14151976.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定