duanmi4379 2015-05-30 21:41
浏览 54
已采纳

在Google App Engine for Go中,属性如何具有多个类型的值?

The Google App Engine for Go datastore docs say, " A property can have values of more than one type". There is no example or further explanation. (Version: appengine 1.9.19.)

How can a property have more than one type if you must declare that property with a specific type in the backing struct?

  • 写回答

1条回答 默认 最新

  • doucu9677 2015-05-31 10:23
    关注

    You do not necessarily have to declare a specific type for a property in a backing struct.

    By implementing the PropertyLoadSaver interface, you can dynamically do whatever you want with the properties of an entity during loading or before saving. See this answer which shows how to represent an entity as a general map[string]interface{} type in Go, so it can have dynamic properties.

    Back to your question:

    A property can have values of more than one type.

    This is true. But if you want to make this work, you will also have to utilize a custom loading/saving mechanism through the PropertyLoadSaver interface.

    First define a backing struct where the property which will have multiple values of different types may be an []interface{}:

    type MyMy struct {
        Objects []interface{}
    }
    

    Next we have to implement PropertyLoadSaver. When loading, we will just append all values to the Objects slice that come with the name "Objects".

    When saving, we will loop over the elements of the Objects slice and send all its values with the same property name. This will ensure they will be saved under the same property, and we also have to specify the Multiple field to be true (multi-value property):

    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
    }
    

    Note that setting a value of type interface{} as the Property.Value would result in an error, that is why I used a Type switch so I will set concrete types. In my example I only supported 3 types (int64, string and float64) but you can just as easily add more types by adding new case branches.

    And using it:

    And finally using our custom MyMy type to save a new entity with property "Objects" which will have multiple values and of different types:

    m := MyMy{[]interface{}{int64(1234), "strval", 32.2}}
    key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "MyMy", nil), &m)
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 像这种代码要怎么跑起来?
  • ¥15 怎么改成循环输入删除(语言-c语言)
  • ¥15 安卓C读取/dev/fastpipe屏幕像素数据
  • ¥15 pyqt5tools安装失败
  • ¥15 mmdetection
  • ¥15 nginx代理报502的错误
  • ¥100 当AWR1843发送完设置的固定帧后,如何使其再发送第一次的帧
  • ¥15 图示五个参数的模型校正是用什么方法做出来的。如何建立其他模型
  • ¥100 描述一下元器件的基本功能,pcba板的基本原理
  • ¥15 STM32无法向设备写入固件