【问题标题】:In Google App Engine for Go, how can a property have values of more than one type?在 Google App Engine for Go 中,一个属性如何具有多个类型的值?
【发布时间】:2015-05-30 21:41:48
【问题描述】:

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

如果您必须在支持结构中声明具有特定类型的属性,那么该属性如何具有多个类型?

【问题讨论】:

    标签: google-app-engine go google-cloud-datastore


    【解决方案1】:

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

    通过实现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 种类型(int64stringfloat64),但您可以通过添加新的 case 分支来轻松添加更多类型。

    并使用它:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2023-03-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-09
      • 1970-01-01
      相关资源
      最近更新 更多