栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

在Go中从Python项目中加载数据存储区实体会导致嵌套的结构切片切片错误

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

在Go中从Python项目中加载数据存储区实体会导致嵌套的结构切片切片错误

我想如果您足够挖掘,就会找到答案:

首先,在Python中定义LocalStructuredProperty属性时,您需要设置

keep_keys=True

class ModelB(ndb.Model):    msg_id = ndb.StringProperty(indexed=False)    cat_ids = ndb.StringProperty(repeated=True, indexed=False)    list_ids = ndb.StringProperty(repeated=True, indexed=False)    default_list_id_index = ndb.IntegerProperty(indexed=False)class ModelA(ndb.Model):    date_join = ndb.DateTimeProperty(auto_now_add=True)    name = ndb.StringProperty()    owner_salutation = ndb.StringProperty(indexed=False)    owner_email_address = ndb.StringProperty()    logo_url = ndb.StringProperty(indexed=False)    ...    messages = ndb.LocalStructuredProperty(ModelB, name='bm', repeated=True, keep_keys=True)

在代码中进行简单的重新定义,然后对实体进行映射,

put()
对每个固定的表示进行固定。

然后在我的Go代码中:

type ModelB struct {    MessageID          string   `datastore:"msg_id,noindex"`    CategoryIDs        []string `datastore:"cat_ids,noindex"`    ListIDs []string `datastore:"list_ids,noindex"`    DefaultListIDIndex int      `datastore:"default_list_id_index,noindex"`}type ModelA struct {    DateJoin          time.Time `datastore:"date_join,"`    Name   string    `datastore:"name,"`    OwnerSalutation   string    `datastore:"owner_salutation,noindex"`    OwnerEmailAddress string    `datastore:"owner_email_address,"`    LogoURLstring    `datastore:"logo_url,noindex"`    Messages          []ModelB  `datastore:"-"`}// Load is implemented for the PropertyLoaderSaver interface.func (s *ModelA) Load(c <-chan datastore.Property) (err error) {    f := make(chan datastore.Property, 32)    errc := make(chan error, 1)    defer func() {        if err == nil { err = <-errc        }    }()    go func() {        defer close(f)        for p := range c { if p.Name == "bm" {     var b ModelB     err := loadLocalStructuredProperty(&b, []byte(p.Value.(string)))     if err != nil {         errc <- err         return     }     s.Messages = append(s.Messages, b) } else {     f <- p }        }        errc <- nil    }()    return datastore.LoadStruct(s, f)}

我不得不从

appengine/datastore
软件包中复制一堆,因为没有导出关键功能,并且为了简化我需要复制的代码量,我放弃了对
Reference
类型的支持。我在问题跟踪器上打开了一张票,看是否可以
loadEntity
导出该函数:https
:
//pre.google.com/p/googleappengine/issues/detail?id=10426

import (        "errors"        "time"    "appengine"        "appengine/datastore"    pb "appengine_internal/datastore"        proto "pre.google.com/p/goprotobuf/proto"    )func loadLocalStructuredProperty(dst interface{}, raw_proto []byte) error {        var val pb.EntityProto        err := proto.Unmarshal(raw_proto, &val)        if err != nil { return err        }        return loadEntity(dst, &val)    }//Copied from appengine/datastore since its not exported// loadEntity loads an EntityProto into PropertyLoadSaver or struct pointer.func loadEntity(dst interface{}, src *pb.EntityProto) (err error) {c := make(chan datastore.Property, 32) errc := make(chan error, 1) defer func() {    if err == nil { err = <-errc        }    }()    go protoToProperties(c, errc, src)    if e, ok := dst.(datastore.PropertyLoadSaver); ok {        return e.Load(c)    }    return datastore.LoadStruct(dst, c)}func protoToProperties(dst chan<- datastore.Property, errc chan<- error, src *pb.EntityProto) {    defer close(dst)    props, rawProps := src.Property, src.RawProperty    for {        var ( x       *pb.Property noIndex bool        )        if len(props) > 0 { x, props = props[0], props[1:]        } else if len(rawProps) > 0 { x, rawProps = rawProps[0], rawProps[1:] noIndex = true        } else { break        }        var value interface{}        if x.Meaning != nil && *x.Meaning == pb.Property_INDEX_VALUE { value = indexValue{x.Value}        } else { var err error value, err = propValue(x.Value, x.GetMeaning()) if err != nil {     errc <- err     return }        }        dst <- datastore.Property{ Name:     x.GetName(), Value:    value, NoIndex:  noIndex, Multiple: x.GetMultiple(),        }    }    errc <- nil}func fromUnixMicro(t int64) time.Time {    return time.Unix(t/1e6, (t%1e6)*1e3)}// propValue returns a Go value that combines the raw PropertyValue with a// meaning. For example, an Int64Value with GD_WHEN becomes a time.Time.func propValue(v *pb.PropertyValue, m pb.Property_Meaning) (interface{}, error) {    switch {    case v.Int64Value != nil:        if m == pb.Property_GD_WHEN { return fromUnixMicro(*v.Int64Value), nil        } else { return *v.Int64Value, nil        }    case v.BooleanValue != nil:        return *v.BooleanValue, nil    case v.StringValue != nil:        if m == pb.Property_BLOB { return []byte(*v.StringValue), nil        } else if m == pb.Property_BLOBKEY { return appengine.BlobKey(*v.StringValue), nil        } else { return *v.StringValue, nil        }    case v.Doublevalue != nil:        return *v.Doublevalue, nil    case v.Referencevalue != nil:        return nil, errors.New("Not Implemented!")    }    return nil, nil}// indexValue is a Property value that is created when entities are loaded from// an index, such as from a projection query.//// Such Property values do not contain all of the metadata required to be// faithfully represented as a Go value, and are instead represented as an// opaque indexValue. Load the properties into a concrete struct type (e.g. by// passing a struct pointer to Iterator.Next) to reconstruct actual Go values// of type int, string, time.Time, etc.type indexValue struct {    value *pb.PropertyValue}


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/484208.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号