【发布时间】:2015-05-30 21:41:48
【问题描述】:
Google App Engine for Go datastore docs 说," 一个属性可以有多个类型的值”。没有示例或进一步解释。(版本:appengine 1.9.19。)
如果您必须在支持结构中声明具有特定类型的属性,那么该属性如何具有多个类型?
【问题讨论】:
标签: google-app-engine go google-cloud-datastore
Google App Engine for Go datastore docs 说," 一个属性可以有多个类型的值”。没有示例或进一步解释。(版本:appengine 1.9.19。)
如果您必须在支持结构中声明具有特定类型的属性,那么该属性如何具有多个类型?
【问题讨论】:
标签: google-app-engine go google-cloud-datastore
您不必为支持结构中的属性声明特定类型。
通过实现PropertyLoadSaver 接口,您可以在加载期间或保存之前动态地对实体的属性进行任何操作。请参阅this answer,它展示了如何将实体表示为 Go 中的一般 map[string]interface{} 类型,因此它可以具有动态属性。
一个属性可以有多个类型的值。
这是真的。但是如果你想完成这项工作,你还必须通过PropertyLoadSaver 接口使用自定义加载/保存机制。
首先定义一个支持struct,其中具有多个不同类型值的属性可能是[]interface{}:
type MyMy struct {
Objects []interface{}
}
接下来我们必须实现PropertyLoadSaver。加载时,我们会将所有值附加到名称为 "Objects" 的 Objects 切片中。
保存时,我们将遍历Objects 切片的元素并发送其所有具有相同属性名称的值。这将确保它们将保存在相同的属性下,我们还必须将Multiple 字段指定为true(多值属性):
func (m *MyMy) Load(ch <-chan datastore.Property) error {
for p := range ch { // Read until channel is closed
if p.Name == "Objects" {
m.Objects = append(m.Objects, p.Value)
}
}
return nil
}
func (m *MyMy) Save(ch chan<- datastore.Property) error {
defer close(ch)
for _, v := range m.Objects {
switch v2 := v.(type) {
case int64: // Here v2 is of type int64
ch <- datastore.Property{Name: "Objects", Value: v2, Multiple: true}
case string: // Here v2 is of type string
ch <- datastore.Property{Name: "Objects", Value: v2, Multiple: true}
case float64: // Here v2 is of type float64
ch <- datastore.Property{Name: "Objects", Value: v2, Multiple: true}
}
}
return nil
}
请注意,将interface{} 类型的值设置为Property.Value 会导致错误,这就是我使用Type switch 的原因,所以我将设置具体类型。在我的示例中,我只支持 3 种类型(int64、string 和 float64),但您可以通过添加新的 case 分支来轻松添加更多类型。
最后使用我们自定义的MyMy 类型来保存具有属性“Objects”的新实体,该实体将具有多个值和不同类型:
m := MyMy{[]interface{}{int64(1234), "strval", 32.2}}
key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "MyMy", nil), &m)
【讨论】: