我正在使用數據存儲的appengine應用程序。我正試圖編碼一個接口並將其存儲到數據存儲區 。但是,當我嘗試從 數據存儲負載,我得到的錯誤:gob:接口僅在編碼上註冊,但不在解碼
gob: name not registered for interface: "main27155.strand"
奇特的事情是load()
方法開始有 稱爲save()
方法後工作。它不再返回錯誤,並且按預期加載數據存儲中保存的所有內容 。但是當我重新啓動實例時, load()
方法再次停止工作。
的加載和保存我提到是指由 datastore.PropertyLoadSaver
接口
定義從它的外觀的方法方法,好像與註冊與採空區 類型/接口問題,但我有完全相同同樣的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()
也許這是一個類型不是導出的問題?我很久沒有與gob合作過,所以我對它的工作原理感到生疏。 –
我第二次Not_a_Golfer的懷疑:從編碼/ gib文檔:「Structs編碼和解碼僅導出的領域。」。因爲這可能與appengine,HTTP請求或數據存儲沒有任何關係:您能否在操場上創建可運行的示例? – Volker
gob包編碼未導出的類型就好了。 [實施例](http://play.golang.org/p/-lu435K4Zt)。 OP,請在進行更改後檢查您是否啓動服務器。 –