datastore: недопустимый тип сущности на Put

Я пытаюсь создать обертку вокруг моих видов, и вот как я это делаю:

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"
}

и причина, по которой я представил 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
}

как вы можете видеть, я использую data.Name() получить имя вида.

когда я пытаюсь сохранить данные, он жалуется:

datastore: invalid entity type

Я прочитал, что это может быть связано с тем, что не передал ссылку на datastore.Put, но я делаю это. Есть идеи?

Я должен добавить, что, когда я проверил тип данных (используя reflect.TypeOf()), то model.Message это тоже правильно. Так что это конкретный тип.

1 ответов


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())

выход (попробуйте на Go Playground):

ptr
interface
ptr
struct

все &data является указателем на интерфейс, и это не разрешено передавать в datastore.Put(). Вы можете только пройти *Message, или если вы хотите передать значение интерфейса (не указатель на интерфейс), затем убедитесь, что реализовали PropertyLoadSaver.