将一个数据存储实体转换为Go中的接口

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

Getting a datastore entity into an interface in Go

问题

我有几个数据存储种类,它们具有相同的字段Id。是否可能创建一个通用函数来获取这个值?类似于这样的代码?

var i interface{}
err = datastore.Get(c, key, &i)
v := reflect.ValueOf(i)
id := v.FieldByName("Id").String()

上述代码会给我一个"datastore: invalid entity type"错误。

英文:

I have a couple of datastore Kinds that have the same field Id. Is it possible to create one generic function that can get me this value? Something similar to this?

var i interface{}
err = datastore.Get(c, key, &i)
v := reflect.ValueOf(i)
id := v.FieldByName("Id").String()

The above code, as it is, gives me a "datastore: invalid entity type" error.

答案1

得分: 8

var i interface{} 不属于任何具体类型。appengine数据存储需要一个具体类型来反序列化数据,因为它使用反射。从文档中看,缺少字段或字段与存储的数据类型不同也会导致返回错误,因此不能仅定义具有ID字段的结构体。

即使如此,您仍然可以使用实现PropertyLoadSaver接口的自定义类型来解决问题,如下所示:

type IdField struct {
  Id string
}

func (f *IdField) Load(ch <-chan Property) error {
  for p := range ch {
    if p.Name == "Id" {
      f.Id = p.Value.(string)
    }
  }
  return nil
}

func (f *IdField) Save(ch chan<- Property) error {
   return fmt.Errorf("Not implemented")
}

var i = &IdField{}
err := datastore.Get(c, key, i)
id := i.Id

这可能不如您希望的那样简洁,但它更加类型安全,不需要反射,并且说明了您可以使用的一般方法来从数据存储中获取部分数据。

英文:

var i interface{} isn't of any concrete type. The appengine datastore requires a concrete type to deserialize the data into since it uses reflection. It looks like from the documentation that missing fields or fields of a different type than the data was stored from will cause an error to be returned as well so you can't create a struct with just the ID field defined.

Even so it's possible you could work something out using a custom type that implements the PropertyLoadSaver interface like so:

type IdField struct {
  Id string
}

function (f *IdField) Load(ch &lt;-chan Property) error {
  for p := range ch {
    if p.Name == &quot;Id&quot; {
      f.Id = p.Value.(string)
    }
  }
  return nil
}

function (f *IdField) Save(ch chan&lt;- Property) error {
   return fmt.Errorf(&quot;Not implemented&quot;)
}

var i = &amp;IdField{}
err := datastore.Get(c, key, i)
id := i.Id

It's probably not as concise as you were hoping but it's a little more typesafe doesn't require reflection and illustrates the general approach you could use to get partial data out of the datastore.

huangapple
  • 本文由 发表于 2012年9月5日 05:50:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/12271836.html
匿名

发表评论

匿名网友

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

确定