Flattening nested structs leads to a slice of slic

2019-05-10 19:44发布

So I have a struct like this

type Bus struct {
    Number          string
    Name            string
    DirectStations  []Station  // Station is another struct
    ReverseStations []Station
}

and I'm trying to store an instance of this to the Datastore:

key := datastore.NewKey(c, "Bus", bus.Number, 0, nil)
_, err := datastore.Put(c, key, &bus)

but I'm getting the error

datastore: 
flattening nested structs leads to a slice of slices: 
field "DirectStations"

How does one solve this?

Edit:

Turns out you can't have a slice of struct, where that struct contains other slices.

2条回答
ら.Afraid
2楼-- · 2019-05-10 20:44

Just encode this struct into json (bytes) and store the json in the datastore

EDIT / UPDATE

package main

import (
    "encoding/json"
    "fmt"
)

type Bus struct {
    Number          string    `json:"number"`
    Name            string    `json:"name"`
    DirectStations  []Station `json:"directstation"` // Station is another struct
    ReverseStations []Station `json:"reversestation"`
}

type Station struct {
    StationName string `json:"stationname"` // these tag names must match exactly  how they look in json
}

func toJson(i interface{}) []byte {
    data, err := json.Marshal(i)
    if err != nil {
        panic(err)
    }

    return data
}
func fromJson(v []byte, vv interface{}) {
    json.Unmarshal(v, vv)

}

func main() {
    bus := Bus{}
    st := []Station{{"station1"}, {"station2"}}
    bus.DirectStations = make([]Station, len(st))
    for i, v := range st {
        bus.DirectStations[i] = v
    }
    bus.Number = "2"
    bus.Name = "BusName"
    js := toJson(bus)
    fmt.Println("JSON OUTPUT", string(js))
    bus2 := Bus{}
    fromJson(js, &bus2)
    fmt.Printf("ORIGINAL STRUCT OUTPUT %#v", bus2)
}

http://play.golang.org/p/neAGgcAIZG

查看更多
Root(大扎)
3楼-- · 2019-05-10 20:47

Another option for anyone that comes here is to just not store the slice of structures as a child in the datastore then just load them up separately when you're loading the obj

Something like:

type Parent struct {
  Id       int64      `json:"id"`
  Nested   []Child    `json:"children" datastore:"-"`  
  ...
}

type Child struct {
  Id       int64      `json:"id"`
  ParentId int64      `json:"parent_id"`
  ...
}

Then when you want to load the parent, let's assume this code is in a service module and you've got a handy data module to actually pull stuff from the datastore (which you probably should)

func LoadParentWithNested(parent_id int64) (Parent, error){
  parent := data.GetParent(parent_id)
  parent.Nested := data.LoadNested(parent.Id)

  return parent
}

Obviously you'll want error checking and all that, but this is kind of what you've got to do for complex nested structures.

查看更多
登录 后发表回答