gpt4 book ai didi

google-app-engine - 我怎样才能在谷歌应用引擎数据存储区中拥有动态属性

转载 作者:IT王子 更新时间:2023-10-29 01:24:54 26 4
gpt4 key购买 nike

我想做类似 Expando Model 的事情python 在应用程序引擎上支持。

Sometimes you don't want to declare your properties ahead of time. A special model subclass, Expando, changes the behavior of its entities so that any attribute assigned (as long as it doesn't start with an underscore) is saved to the Datastore.

我如何在 Go 中执行此操作?

最佳答案

事先注意:

有 2 个 API。具有导入路径 appengine/datastore 的那个使用 channel 作为参数。另一个具有导入路径 google.golang.org/appengine/datastore 使用 slice 。根据您的情况调整以下示例。有关详细信息,请参阅此问题:How to correctly import Golang appengine?


具有动态属性的实体的关键是 PropertyLoadSaver界面。通过实现此接口(interface),您可以在保存时动态地构造要保存的实体的属性。

此外,为了不必自己执行此操作,Go AppEngine 平台提供了一个 PropertyList type 基本上是属性列表( slice )Property它还实现了 PropertyLoadSaver

所以Go中的Expando模型是PropertyList。只需添加您希望您的实体拥有的属性,并保存此 PropertyList 值。

这是一个例子:

c := appengine.NewContext(r)

props := datastore.PropertyList{
datastore.Property{Name: "time", Value: time.Now()},
datastore.Property{Name: "email", Value: "me@myhost.com"},
}

k := datastore.NewIncompleteKey(c, "DynEntity", nil)
key, err := datastore.Put(c, k, &props)
c.Infof("%v %v", key, err)

此示例保存一个名为 "DynEntity" 的实体,该实体具有 2 个动态属性:"time""email"

由于 PropertyList 类型是一个 slice ,您还可以使用内置的 append()函数为其添加属性,因此您也可以像这样初始化 props:

var props datastore.PropertyList
props = append(props, datastore.Property{Name:"time", Value: time.Now()})
props = append(props, datastore.Property{Name:"email", Value: "me@myhost.com"})

map 转换为动态实体

PropertyLoadSaver接口(interface)并不复杂,我们可以自己实现。在下面的示例中,我在自定义类型上实现了它,它是一个简单的 map:

type DynEnt map[string]interface{}

func (d *DynEnt) Load(props []datastore.Property) error {
// Note: you might want to clear current values from the map or create a new map
for _, p := range props {
(*d)[p.Name] = p.Value
}
return nil
}

func (d *DynEnt) Save() (props []datastore.Property, err error) {
for k, v := range *d {
props = append(props, datastore.Property{Name: k, Value: v})
}
return
}

下面是使用 channel 而不是 slice 的“旧”界面的实现方式:

type DynEnt map[string]interface{}

func (d *DynEnt) Load(ch <-chan datastore.Property) error {
// Note: you might want to clear current values from the map or create a new map
for p := range ch { // Read until channel is closed
(*d)[p.Name] = p.Value
}
return nil
}

func (d *DynEnt) Save(ch chan<- datastore.Property) error {
defer close(ch) // Channel must be closed
for k, v := range *d {
ch <- datastore.Property{Name: k, Value: v}
}
return nil
}

现在我们可以像使用 Go 中的任何其他映射一样使用我们的 DynEnt 类型,并且由于它实现了 PropertyLoadSaver,它可以保存为一个实体(和 任何实体都可以加载到其中):

c := appengine.NewContext(r)

d := DynEnt{"email": "me@myhost.com", "time": time.Now()}

k := datastore.NewIncompleteKey(c, "DynEntity", nil)
key, err := datastore.Put(c, k, &d)
c.Infof("%v %v", key, err)

关于google-app-engine - 我怎样才能在谷歌应用引擎数据存储区中拥有动态属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29885431/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com