数据存储:Put上的实体类型无效

Max*_*Zoo 7 google-app-engine go google-cloud-datastore

我正在尝试创建一个围绕我的种类的包装器,这是我如何做到这一点:

package model

import (
    "time"
)

type Kind interface {
    Name() string
}

type Message struct {
    Text      string
    CreatedOn time.Time
    UserId    string
}

func (q Message) Name() string {
    return "MESSAGE"
}
Run Code Online (Sandbox Code Playgroud)

我介绍的原因type Kind interface是:

// Stores the given model for the the kind in data store
func Store(req *http.Request, data Kind) error {
    ctx := appengine.NewContext(req)
    key := datastore.NewKey(ctx, data.Name(), "", 0, nil)
    _, err := datastore.Put(ctx, key, &data)
    return err
}
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我正在使用data.Name()各种名称.

当我尝试保存数据时,它会抱怨:

datastore: invalid entity type
Run Code Online (Sandbox Code Playgroud)

我读到这可能是因为没有传递引用datastore.Put,但我这样做.任何的想法?

我必须补充一点,当我检查数据类型(使用reflect.TypeOf())时,它model.Message也是正确的.所以它是一种具体的类型.

icz*_*cza 13

datastore.Put()期望实体数据作为结构指针或任何实现的值PropertyLoadSaver.这在文档中明确说明:

src 必须是结构指针或实现 PropertyLoadSaver

传递给datastore.Put()它的是指针值,指向接口的指针.存储在接口中的值确实是具体类型model.Message,但它们并不相同.

你不能使用,reflect.TypeOf().String()因为在接口的情况下它会告诉你存储在接口中的具体类型(因此它可能会产生误导).

请参阅此代码以演示差异:

var data Kind = Message{}
fmt.Println(reflect.TypeOf(&data).Kind())
fmt.Println(reflect.TypeOf(&data).Elem().Kind())

var msg Message = Message{}
fmt.Println(reflect.TypeOf(&msg).Kind())
fmt.Println(reflect.TypeOf(&msg).Elem().Kind())
Run Code Online (Sandbox Code Playgroud)

输出(在Go Playground上试试):

ptr
interface
ptr
struct
Run Code Online (Sandbox Code Playgroud)

总而言之,&data是一个指向接口的指针,并且不允许传递给它datastore.Put().您只能传递*Message,或者如果要传递接口值(不是指向接口的指针),请确保实现PropertyLoadSaver.