我正在使用数据存储开发应用引擎应用程序。我正在尝试采空 对接口(interface)进行编码并将其存储到数据存储中。但是当我尝试从加载 数据存储,我收到错误:
gob: name not registered for interface: "main27155.strand"
奇怪的是 load() 方法在加载后开始工作
调用了 save() 方法。它不再返回错误,一切都保存了
在数据存储中按预期加载。但是当我重新启动实例时,
load() 方法再次停止工作。
我提到的加载和保存方法是指定义的方法
datastore.PropertyLoadSaver 接口(interface)
从外观上看,注册似乎有问题
与 gob 的类型/接口(interface),但我有完全相同的 gob.Register() 调用
load() 和 save() 方法。
我什至尝试从加载和保存方法中删除 gob.Register() 调用
并将其添加到 init()。观察到完全相同的行为。
如何在冷启动时加载我的数据存储?
type bio struct {¬
Id string¬
Hp int¬
godie chan bool //should be buffered¬
dam chan int¬
Genetics dna¬
}¬
type dna interface {
decode() mRNA
Get(int) trait
Set(int, trait)
Duplicate() dna
Len() int
}
type trait interface {
mutate() trait
}
// implements dna{}
type strand []trait
// implements trait{}
type tdecoration string
type color struct {
None bool // If true, colors are not shown in theme
Bg bool // If true, color is a background color
R int // 0-255
G int
B int
}
.
func start(w http.ResponseWriter, r *http.Request) error {
c := appengine.NewContext(r)
var bs []bio
if _, err := datastore.NewQuery("bio").GetAll(c, &bs); err != nil {
log.Println("bs is len: ", len(bs))
return err
}
...
return nil
}
func stop(w http.ResponseWriter, r *http.Request) error {
c := appengine.NewContext(r)
log.Println("Saving top 20 colors")
var k []*datastore.Key
var bs []*bio
stat := getStats()
for i, b := range stat.Leaderboard {
k = append(k, datastore.NewKey(c, "bio", b.Id, 0, nil))
bv := b
bs = append(bs, &bv)
// At most 20 bios survive across reboots
if i > 178 {
break
}
}
// Assemble slice of keys for deletion
dk, err := datastore.NewQuery("bio").KeysOnly().GetAll(c, nil)
if err != nil {
return errors.New(fmt.Sprintf("Query error: %s", err.Error()))
}
fn := func(c appengine.Context) error {
// Delete all old entries
err := datastore.DeleteMulti(c, dk)
if err != nil {
return errors.New(fmt.Sprintf("Delete error: %s", err.Error()))
}
// save the elite in the datastore
_, err = datastore.PutMulti(c, k, bs)
if err != nil {
return err
}
return nil
}
return datastore.RunInTransaction(c, fn, &datastore.TransactionOptions{XG: true})
}
// satisfy datastore PropertyLoadSaver interface ===============================
func (b *bio) Load(c <-chan datastore.Property) error {
gob.Register(&color{})
gob.Register(new(tdecoration))
var str strand
gob.Register(str)
tmp := struct {
Id string
Hp int
Gengob []byte
}{}
if err := datastore.LoadStruct(&tmp, c); err != nil {
return err
}
b.Id = tmp.Id
b.Hp = tmp.Hp
return gob.NewDecoder(strings.NewReader(string(tmp.Gengob))).Decode(&(b.Genetics))
}
func (b *bio) Save(c chan<- datastore.Property) error {
defer close(c)
gob.Register(&color{})
gob.Register(new(tdecoration))
var str strand
gob.Register(str)
var buf bytes.Buffer
gen := b.Genetics
if err := gob.NewEncoder(&buf).Encode(&gen); err != nil {
log.Println(err)
return err
}
dp := []datastore.Property{
{Name: "Id", Value: b.Id},
{Name: "Hp", Value: int64(b.Hp)},
{Name: "Gengob", Value: buf.Bytes(), NoIndex: true},
}
for _, p := range dp {
c <- p
}
return nil
}
附加信息:在我填充数据存储区之前不存在此行为
在 stop() 中调用 datastore.RunInTransaction()
最佳答案
使用 RegisterName() 在 init() 函数中注册所有类型.从商店中删除所有现有数据,您应该一切顺利。
每次构建应用程序时,App Engine 都会为主包生成一个经过修饰的名称。 Register() 生成的名称包括这个损坏的包名称。任何用错位名称编码的 gob 只能使用相同的应用程序版本读取。如果您通过修改代码导致应用程序重新构建,则该应用程序将无法解码之前存储的 gobs。
关于google-app-engine - 采空区 : interface is only registered on Encode but not on Decode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417541/