在 Google App Engine for Go 中,属性 怎么可能有不止一种类型的值?

In Google App Engine for Go, how can a property have values of more than one type?

Go 的 Google App Engine datastore docs 说,” 属性 可以有不止一种类型的值。没有示例或进一步解释。(版本:appengine 1.9.19。)

如果必须在支持结构中声明 属性 具有特定类型,那么 属性 怎么可能有多个类型?

您不必在支持结构中为 属性 声明特定类型。

通过实现 PropertyLoadSaver interface, you can dynamically do whatever you want with the properties of an entity during loading or before saving. See ,它展示了如何在 Go 中将实体表示为通用 map[string]interface{} 类型,因此它可以具有动态属性。

回到你的问题:

A property can have values of more than one type.

这是真的。但是如果你想让这个工作,你还必须通过 PropertyLoadSaver 接口使用自定义 loading/saving 机制。

首先定义一个支持 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 种类型(int64stringfloat64),但您可以通过添加新的 case 分支轻松添加更多类型。

并使用它:

最后使用我们的自定义 MyMy 类型来保存具有 属性 "Objects" 的新实体,它将具有多个值和不同类型:

m := MyMy{[]interface{}{int64(1234), "strval", 32.2}}
key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "MyMy", nil), &m)