2016-05-28 13 views
5

Sto cercando di creare un wrapper per i miei generi ed ecco come lo faccio:datastore: non valida tipo di entità sul 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" 
} 

E la ragione per cui ho introdotto 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 
} 

Come potete vedere, sto usando data.Name() per ottenere il nome del tipo.

Quando cerco di salvare i dati, si lamenta:

datastore: invalid entity type 

Ho letto che questo potrebbe essere causa di non passare il riferimento alla datastore.Put, ma sto facendo questo. Qualche idea?

Devo aggiungere che quando ho controllato il tipo di dati (usando reflect.TypeOf()), è model.Message che è anche corretto. Quindi è un tipo concreto.

risposta

6

datastore.Put() prevede i dati dell'entità come un puntatore di struttura o qualsiasi valore che implementa PropertyLoadSaver. Questo è chiaramente affermato nel suo documento:

src deve essere un puntatore struct o implementare PropertyLoadSaver

Cosa si passa ad datastore.Put() è un valore puntatore, un puntatore a un'interfaccia. È vero che il valore memorizzato nell'interfaccia è di tipo concreto model.Message, ma non sono uguali.

Non è possibile utilizzare reflect.TypeOf().String() perché in caso di interfaccia indica il tipo concreto memorizzato nell'interfaccia (quindi potrebbe essere fuorviante).

Vedere questo codice per dimostrare la differenza:

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

uscita (provate sul Go Playground):

ptr 
interface 
ptr 
struct 

Tutto sommato, &data è un puntatore a un'interfaccia, e che è non è consentito passare a datastore.Put(). È possibile passare solo *Message o se si desidera passare un valore di interfaccia (NON un puntatore a un'interfaccia), quindi assicurarsi di implementare PropertyLoadSaver.

+0

grazie per la risposta spiegata alla mia confusione sul tipo concreto. Sto cercando di capire come l'implementazione di 'PropertyLoadSaver' (https://cloud.google.com/appengine/docs/go/datastore/reference#hdr-The_PropertyLoadSaver_Interface) mi può aiutare in questa situazione. Quello che mi piacerebbe ottenere qui è di creare una funzione generica che possa memorizzare qualsiasi tipo e che possa ottenere il nome del tipo usando i metadati allegati al tipo stesso. Ho cercato di farlo introducendo 'Name()'. Hai qualche soluzione a questo? Quindi il chiamante non ha bisogno di specificare il nome del tipo tutto il tempo. –

+0

@MaxZooZoo 'Name()' è un nome di metodo troppo generico, sceglierei qualcosa di più specifico (ad esempio 'EntityName()'). Ma non vorrei seguire questa strada, il nome dell'entità è piuttosto una meta-informazione e non qualcosa che dovrebbe essere decisa da un'implementazione concreta. Sarebbe meglio aggiungere un nuovo campo alle struct, usando [struct tags] (http://stackoverflow.com/questions/10858787/what-are-the-uses-for-tags-in-go/30889373#30889373) a escludilo, ma il valore del tag potrebbe contenere le informazioni per il nome dell'entità.O l'opzione ancora migliore sarebbe quella di creare un registro di nomi, un mapping 'map [Type] string' da Go al nome dell'entità. – icza

+0

Questo è esattamente il mio punto. Mi è piaciuto l'approccio del tag, ma mi chiedevo se c'è un modo per taggare una struct stessa poiché i metadati devono essere collegati all'intera struct invece di un campo specifico nella struct. Se hai familiarità con le annotazioni in Java, sarebbe un'annotazione di classe. Abbiamo una cosa del genere in Go? –

Problemi correlati