将嵌套的结构扁平化会导致一个切片的切片。

huangapple go评论109阅读模式
英文:

Flattening nested structs leads to a slice of slices

问题

所以我有一个像这样的结构体:

  1. type Bus struct {
  2. Number string
  3. Name string
  4. DirectStations []Station // Station 是另一个结构体
  5. ReverseStations []Station
  6. }

我试图将这个结构体的实例存储到 Datastore 中:

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

但是我得到了错误信息:

  1. datastore:
  2. flattening nested structs leads to a slice of slices:
  3. field "DirectStations"

如何解决这个问题?

编辑:

事实证明,你不能有一个包含其他切片的结构体切片。

英文:

So I have a struct like this

  1. type Bus struct {
  2. Number string
  3. Name string
  4. DirectStations []Station // Station is another struct
  5. ReverseStations []Station
  6. }

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

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

but I'm getting the error

  1. datastore:
  2. flattening nested structs leads to a slice of slices:
  3. field "DirectStations"

How does one solve this?

Edit:

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

答案1

得分: 3

只需将此结构编码为 JSON(字节),并将 JSON 存储在数据存储中。

编辑/更新

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type Bus struct {
  7. Number string `json:"number"`
  8. Name string `json:"name"`
  9. DirectStations []Station `json:"directstation"` // Station is another struct
  10. ReverseStations []Station `json:"reversestation"`
  11. }
  12. type Station struct {
  13. StationName string `json:"stationname"` // 这些标签名称必须与 JSON 中的名称完全匹配
  14. }
  15. func toJson(i interface{}) []byte {
  16. data, err := json.Marshal(i)
  17. if err != nil {
  18. panic(err)
  19. }
  20. return data
  21. }
  22. func fromJson(v []byte, vv interface{}) {
  23. json.Unmarshal(v, vv)
  24. }
  25. func main() {
  26. bus := Bus{}
  27. st := []Station{{"station1"}, {"station2"}}
  28. bus.DirectStations = make([]Station, len(st))
  29. for i, v := range st {
  30. bus.DirectStations[i] = v
  31. }
  32. bus.Number = "2"
  33. bus.Name = "BusName"
  34. js := toJson(bus)
  35. fmt.Println("JSON OUTPUT", string(js))
  36. bus2 := Bus{}
  37. fromJson(js, &bus2)
  38. fmt.Printf("ORIGINAL STRUCT OUTPUT %#v", bus2)
  39. }

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

英文:

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

EDIT / UPDATE

  1. package main
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. )
  6. type Bus struct {
  7. Number string `json:"number"`
  8. Name string `json:"name"`
  9. DirectStations []Station `json:"directstation"` // Station is another struct
  10. ReverseStations []Station `json:"reversestation"`
  11. }
  12. type Station struct {
  13. StationName string `json:"stationname"` // these tag names must match exactly how they look in json
  14. }
  15. func toJson(i interface{}) []byte {
  16. data, err := json.Marshal(i)
  17. if err != nil {
  18. panic(err)
  19. }
  20. return data
  21. }
  22. func fromJson(v []byte, vv interface{}) {
  23. json.Unmarshal(v, vv)
  24. }
  25. func main() {
  26. bus := Bus{}
  27. st := []Station{{"station1"}, {"station2"}}
  28. bus.DirectStations = make([]Station, len(st))
  29. for i, v := range st {
  30. bus.DirectStations[i] = v
  31. }
  32. bus.Number = "2"
  33. bus.Name = "BusName"
  34. js := toJson(bus)
  35. fmt.Println("JSON OUTPUT", string(js))
  36. bus2 := Bus{}
  37. fromJson(js, &bus2)
  38. fmt.Printf("ORIGINAL STRUCT OUTPUT %#v", bus2)
  39. }

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

答案2

得分: 0

对于来到这里的任何人来说,另一个选择是在数据存储中不将结构片段作为子项存储,而是在加载对象时单独加载它们。

类似这样:

  1. type Parent struct {
  2. Id int64 `json:"id"`
  3. Nested []Child `json:"children" datastore:"-"`
  4. ...
  5. }
  6. type Child struct {
  7. Id int64 `json:"id"`
  8. ParentId int64 `json:"parent_id"`
  9. ...
  10. }

然后,当您想要加载父项时,假设此代码位于服务模块中,并且您有一个方便的数据模块来从数据存储中实际提取数据(您可能应该有这样一个模块):

  1. func LoadParentWithNested(parent_id int64) (Parent, error){
  2. parent := data.GetParent(parent_id)
  3. parent.Nested = data.LoadNested(parent.Id)
  4. return parent
  5. }

显然,您需要进行错误检查等操作,但这是处理复杂嵌套结构的一种方法。

英文:

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:

  1. type Parent struct {
  2. Id int64 `json:"id"`
  3. Nested []Child `json:"children" datastore:"-"`
  4. ...
  5. }
  6. type Child struct {
  7. Id int64 `json:"id"`
  8. ParentId int64 `json:"parent_id"`
  9. ...
  10. }

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)

  1. func LoadParentWithNested(parent_id int64) (Parent, error){
  2. parent := data.GetParent(parent_id)
  3. parent.Nested := data.LoadNested(parent.Id)
  4. return parent
  5. }

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

huangapple
  • 本文由 发表于 2014年9月13日 20:22:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/25823186.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定