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

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

Flattening nested structs leads to a slice of slices

问题

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

type Bus struct {
    Number          string
    Name            string
    DirectStations  []Station  // Station 是另一个结构体
    ReverseStations []Station
}

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

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

但是我得到了错误信息:

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

如何解决这个问题?

编辑:

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

英文:

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.

答案1

得分: 3

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

编辑/更新

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"` // 这些标签名称必须与 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

英文:

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

答案2

得分: 0

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

类似这样:

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

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

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

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

  return parent
}

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

英文:

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.

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:

确定