PropertyLoadSaver for struct with slice and map example?

507 views
Skip to first unread message

nvcnvn

unread,
May 17, 2014, 6:57:37 AM5/17/14
to google-ap...@googlegroups.com
for example:

type Bar struct {
  X, Y int64
}
type Foo struct {
  Additional map[string]string
  Bar []Bar
}

Because of the map[string]string I need to use PropertyLoadSaver interface, the map is handled simple but I got some trouble with the slice of Bar. I hope someone can show me the example how to handle slice of struct.
Bellow is my code:

func (f *Foo) Load(c <-chan datastore.Property) error {
  for p := range c {
    if strings.HasPrefix(p.Name, "Additional.") {
      f.Additional[p.Name[11:]] = string(p.Value)
    }
  }
  return nil
}
func (f *Foo) Save(c chan<- datastore.Property) error {
  defer close(c)
  for key, val :=range f.Additional {
    c <- datastore.Property{
      Name:  "Additional."+key,
      Value: val,
    }
  }
  return nil
}

Glenn Lewis

unread,
May 17, 2014, 9:21:51 AM5/17/14
to nvcnvn, google-appengine-go
Here is a completely wild shot-in-the-dark, as I have not used the PropertyLoadSaver yet in my apps.
So take this with a grain of salt, and maybe someone with more experience will reply with their nicer solution.
(I think I may have got the type assertions wrong, but you can figure that out with the compiler.)
I hope this helps.
-- Glenn

import (
"fmt"
"regexp"
"strconv"
"strings"

"appengine/datastore"
)

type Bar struct {
X, Y int64
}
type Foo struct {
Additional map[string]string
Bar        []Bar
}

func (f *Foo) Load(c <-chan datastore.Property) error {
barRE := regexp.MustCompile(`^Bar\.(\d+)\.(\d+).([XY])$`)
for p := range c {
if strings.HasPrefix(p.Name, "Additional.") {
f.Additional[p.Name[11:]] = string(p.Value)
}
if m := barRE.FindStringSubmatch(p.Name); m != nil {
size, err := strconv.Atoi(m[1])
if err != nil {
return err
}
i, err := strconv.Atoi(m[2])
if err != nil {
return err
}
if f.Bar == nil {
f.Bar = make([]Bar, size)
}
switch m[3] {
case "X":
f.Bar[i].X = int64(p.Value)
case "Y":
f.Bar[i].Y = int64(p.Value)
}
}
}
return nil
}
func (f *Foo) Save(c chan<- datastore.Property) error {
defer close(c)
for key, val := range f.Additional {
c <- datastore.Property{
Name:  "Additional." + key,
Value: val,
}
}
for i, val := range f.Bar {
c <- datastore.Property{
Name:  fmt.Sprintf("Bar.%d.%d.X", len(f.Bar), i),
Value: val.X,
}
c <- datastore.Property{
Name:  fmt.Sprintf("Bar.%d.%d.Y", len(f.Bar), i),
Value: val.Y,
}
}
return nil
}

nvcnvn

unread,
May 17, 2014, 10:32:08 AM5/17/14
to google-ap...@googlegroups.com, nvcnvn
Hi Glenn, thanks for you solution :)

But after rereading the datastore package referrence I found the solution of appengine is turn a slice of struct into some slice.

Glenn Lewis

unread,
May 17, 2014, 10:40:33 AM5/17/14
to nvcnvn, google-appengine-go

Cool! I am glad you found the answer.
If you wouldn't mind sharing an updated example on this list, that would be great.
Thanks!

--
You received this message because you are subscribed to the Google Groups "google-appengine-go" group.
To unsubscribe from this group and stop receiving emails from it, send an email to google-appengin...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Nguyễn Văn Cao Nguyên

unread,
May 17, 2014, 11:32:49 AM5/17/14
to Glenn Lewis, google-appengine-go
(I get some trouble with replying using group web interface)

I just write down and test the code a litle, here is my implement
func (f *Foo) Load(c <-chan datastore.Property) error {
f.Additional = make(map[string]string)
f.Bar = make([]Bar, 0, 2) // somehow to know the length?
countBar := 0

for p := range c {
if strings.HasPrefix(p.Name, "Additional.") {
f.Additional[p.Name[11:]] = p.Value.(string)
} else if p.Name == "Bar.X" {
f.Bar = append(f.Bar, Bar{X: p.Value.(int64)})
} else if p.Name == "Bar.Y" {
f.Bar[countBar].Y = p.Value.(int64)
countBar++

}
}
return nil
}
func (f *Foo) Save(c chan<- datastore.Property) error {
defer close(c)
for i := 0; i < len(f.Bar); i++ {
c <- datastore.Property{
Name:     "Bar.X",
Value:    int64(f.Bar[i].X),
Multiple: true,
}
c <- datastore.Property{
Name:     "Bar.Y",
Value:    int64(f.Bar[i].Y),
Multiple: true,

}
}
for key, val := range f.Additional {
c <- datastore.Property{
Name:  "Additional." + key,
Value: val,
}
}
return nil
}

Here is an full application: http://play.golang.org/p/5vrBqE_VOf 
--
Nguyễn Văn Cao Nguyên
    /**
     * Contact : +84+935704595
     * Blog      :  http://nguyen.open-vn.org
     */
Reply all
Reply to author
Forward
0 new messages