Background
I've done a fair amount of spec reading and code testing and I think the answer is no, but I want to make sure I'm not missing anything.
Goal
Basically, I'm trying to create a Active Record style ORM for Go, because I like how readable it is and how abstracted it is from its back end data store. I'd rather write user.Save()
than data.Save(user)
by embedding common CRUD methods on the user struct.
Example
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
Question
Is there a way to make top-level fields (not sure what the correct term in Go is for these) accessible from embedded methods (eg: s.Name
or s.Method()
?
Thank you donating your time to a new Gopher.
Go doesn't provide any support for what you're after: the receiver of your Test
method is a Bar
pointer, and there is no way to tell whether it is embedded or not.
If you really want to go this route, one option would be to add an interface{}
member to Bar
and require that types that it be set to the containing type. Initialising this member could either be the responsibility of whoever created the value, or perhaps require callers to pass the value to some ORM method to set it. This isn't particularly pretty, but it's probably the best you can do.
With that out of the way, is it really that bad to structure the API as db.Save(user)
rather than user.Save()
? The former offers an obvious way to extend to multiple databases, while the latter seems more likely to rely on global state.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With