2013-11-23 16 views
5

SfondoI metodi incorporati possono accedere ai campi "parent"?

Ho fatto una buona dose di lettura specifiche e test del codice e credo che la risposta è no, ma voglio fare in modo che non mi manca nulla.

Goal

Fondamentalmente, io sto cercando di creare un ORM Record stile attivo per Go, perché mi piace come leggibile è e come astratta è dal suo archivio di dati back-end. Preferisco scrivere user.Save() rispetto a data.Save(user) incorporando i metodi CRUD comuni sulla struttura dell'utente.

Esempio

package main 

import (
    "fmt" 
    "reflect" 
) 

func main() { 
    test := Foo{Bar: &Bar{}, Name: "name"} 
    test.Test() 
} 

type Foo struct { 
    *Bar 
    Name string 
} 

func (s *Foo) Method() { 
    fmt.Println("Foo.Method()") 
} 

type Bar struct { 
} 

func (s *Bar) Test() { 
    t := reflect.TypeOf(s) 
    v := reflect.ValueOf(s) 
    fmt.Printf("model: %+v %+v %+v\n", s, t, v) 
    fmt.Println(s.Name) 
    s.Method() 
} 

http://play.golang.org/p/cWyqqVSKGH

Domanda

C'è un modo per rendere i campi di alto livello (non so cosa il termine corretto in Go è per questi) accessibili da metodi incorporati (ad esempio: s.Name o s.Method()?

Grazie per aver donato il tuo tempo a un nuovo Gopher.

+0

Vedere la soluzione per la domanda simile su questa altra discussione: https://stackoverflow.com/questions/22153269/how-to-reflect-fields-of-contain-struct-from-a-method-of-the-embedded -struct? rq = 1 –

risposta

1

Go non fornisce alcun supporto per quello che stai cercando: il ricevitore del tuo metodo Test è un puntatore Bar e non c'è modo di sapere se è incorporato o meno.

Se si vuole veramente percorrere questa rotta, un'opzione potrebbe essere quella di aggiungere un membro interface{} a Bar e richiedere i tipi da impostare sul tipo di contenuto. L'inizializzazione di questo membro potrebbe essere responsabilità di chiunque abbia creato il valore o, in alternativa, richiedere ai chiamanti di passare il valore a un metodo ORM per impostarlo. Questo non è particolarmente carino, ma probabilmente è il meglio che puoi fare.

In questo modo, è davvero così difficile strutturare l'API come db.Save(user) anziché user.Save()? Il primo offre un modo ovvio per estendere a più database, mentre il secondo sembra più probabile che faccia affidamento sullo stato globale.

+1

Questo è esattamente il percorso che ho seguito. Non risponderò alla mia domanda da quando hai postato il tuo per primo, ma fornirò la mia soluzione per complimentarmi con la tua risposta: http://play.golang.org/p/v7lC0swB3s. Per quanto riguarda il motivo per cui vorrei evitare 'db.Salva (e utente) ', richiede più specifiche per essere gestito dall'applicazione. La mia idea per un ORM ti consente di impostare un driver db attivo e poi di dimenticartene in modo che tu possa concentrarti sul modello CRUD nel modo più preciso possibile. Grazie per il tuo tempo! – Brenden

+0

@Brenden hai mai implementato questo approccio alla riflessione? Lo hai trovato eseguito abbastanza bene e sei stato contento del sovraccarico e della "magia"? – Xeoncross

0

(Se ho capito correttamente la tua domanda,) no, l'incorporamento non è un'eredità. Sembra che quello che stai cercando sia un'interfaccia

type Saver interface { 
    Save() error 
} 

quindi le parti interessate possono implementarlo.

È possibile avere una struttura comune base o qualsiasi altra cosa che implementa metodi comuni e quindi ogni struttura di livello superiore può incorporare base per consentire loro di condividere l'implementazione.

+1

Voglio evitare di avere un'implementazione personalizzata per ogni struttura che implementa l'interfaccia. – Brenden

Problemi correlati