In Google App Engine for Go, how can a property have values ββof more than one type?
Google App Engine for the Go datastore docs says, "A property can have more than one type of value . " There is no example or additional explanation. (Version: appengine 1.9.19.)
How does a property have more than one type if you have to declare that property with a specific type in the backing structure?
source to share
You do not need to declare a specific type for the property in the backing structure.
By injecting PropertyLoadSaver
, you can dynamically do whatever you want with the properties of the object during load or before saving. See this answer which shows how to represent an object as a generic type map[string]interface{}
in Go, so it can have dynamic properties.
Back to your question:
A property can have more than one type of value.
It's right. But if you want to make this work, you will also have to use your own load / save mechanism through the interface PropertyLoadSaver
.
Define a fallback first struct
, where a property that will have multiple values ββof different types could be []interface{}
:
type MyMy struct {
Objects []interface{}
}
Then we have to implement PropertyLoadSaver
. On load, we'll just add all the values ββto the slice Objects
, which will have a name "Objects"
.
On saving, we will iterate over the slice items Objects
and send all of its values ββwith the same property name. This ensures they are stored under the same property, and we must also specify the field Multiple
as a true
(multivalued 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
}
Please note that setting the value of type interface{}
to as Property.Value
will result in an error, so I used a type switch so I will set specific types. In my example, I only supported 3 types ( int64
, string
and float64
), but you can simply add more types by adding new branches case
.
And using it:
And finally, using our custom type MyMy
to save a new object with the Objects property, which will have multiple values ββand different types:
m := MyMy{[]interface{}{int64(1234), "strval", 32.2}}
key, err := datastore.Put(c, datastore.NewIncompleteKey(c, "MyMy", nil), &m)
source to share