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 I understood your question correctly,) no, embedding isn't inheritance. It sounds like what you're actually after is an interface
type Saver interface {
Save() error
}
then the relevant parties can implement that.
You can have a common struct base or whatever that implements common methods and then each higher-level struct can embed base to allow them to share implementation.
Related
I have the following simple generics based go package that implements the GoF Visitor pattern:
package patterns
type Social interface {
AcceptVisitor(visitor *Visitor)
}
type Component struct {
}
func (c *Component) AcceptVisitor(visitor *Visitor) {
visitor.VisitComponent(c)
}
type Collection[T Social] struct {
Component
items[]T
}
func (c *Collection[T]) AcceptVisitor(visitor *Visitor) {
visitor.VisitCollection(c) // <- Error Here
}
type Visitor struct {
}
func (v *Visitor) VisitComponent(component *Component) {
}
func (v *Visitor) VisitCollection(collection *Collection[Social]) {
for _, item := range collection.items {
item.AcceptVisitor(v)
}
}
The compiler gives the following error:
./patterns.go:20:26: cannot use c (variable of type *Collection[T]) as
type *Collection[Social] in argument to visitor.VisitCollection
This seems strange to me since the generic type T is constrained as Social.
I tried a couple things:
Replaced the Visitor abstract type with an interface definition. This
resulted in circular dependencies between the Social and Visitor
interfaces.
Removed the generics from the declarations which fixes the problem
but we pretty much need generics for the Collection type.
It seems like go should be able to handle the generics in this code.
POSSIBLE SOLUTION:
After a really helpful discussion with #blackgreen we decided that the problem shows up due to a few things:
Go, being (truly) strictly typed, does not allow an argument that is being passed into a function to be "narrowed" to a subset of the original type even though the compiler could still prove it to be safe. Whether or not Go should allow narrowing is up for debate.
Go does not allow generic constraints on a method since the constraints might conflict with generic constraints on the structure associated with the method.
Go, rightly so, does not allow circular dependencies. We could abstract all the dependencies for the Visitor pattern into interfaces but would then have the circular dependencies required by the "double dispatch" aspect of the pattern.
To work-around these items, and still get the benefits of the Visitor pattern, we can change the VisitXYZ() methods in the Visitor structure to be (potentially generic) functions that each take a *Visitor argument as the first parameter of the function and the object being visited as the second parameter.
I posted this solution in the Go Playground: https://go.dev/play/p/vV7v61teFbj
NOTE: Even though this possible solution does appear to solve the problem, it really doesn't. If you think about writing several different types of Visitors (one for pretty printing, one for copying, one for sorting, etc.) you quickly realize that since the VisitXYZ() functions are not methods, you cannot have multiple versions of each function for each Visitor type. In the end, the fact that the Visitor pattern really does require a circular dependency between the Social interface and the Visitor interface dooms it for Go. I am closing this post but will leave the analysis so that others won't need to repeat it.
I came to the conclusion that generics make this pattern worse. By parametrizing the Collection struct, you force items []T to have the same elements. With plain interfaces instead you can have dynamic dispatch, hence allow items to contain different implementations. This alone should be sufficient reason.
This is a minimal implementation without generics, adapted from some Java examples (runnable code):
Main interfaces:
type Visitor func(Element)
type Element interface {
Accept(Visitor)
}
An implementor:
type Foo struct{}
func (f Foo) Accept(visitor Visitor) {
visitor(f)
}
The container:
type List struct {
elements []Element
}
func (l *List) Accept(visitor Visitor) {
for _, e := range l.elements {
e.Accept(visitor)
}
visitor(l)
}
The visitor itself, as a regular function. And here you can define any function at all freely. Being untyped, you can pass it directly as a Visitor argument:
func doVisitor(v Element) {
switch v.(type) {
case *List:
fmt.Println("visiting list")
case Foo:
fmt.Println("visiting foo")
case Bar:
fmt.Println("visiting bar")
}
}
I have a function which takes an interface, like this:
func method(data interface{})
.. because I need to process different structs which have common fields/methods. In this function I use data tens or hundreds of times, in different places. It's really unpleasant to add switch a.(type) { case .. case .. all the time.
Is there a way to create a variable with just one switch with needed type and then just use this variable everywhere later? Something like:
var a .... // something here
switch data.(type) {
case *Struct1:
a = data.(*Struct1)
case *Struct2:
a = data.(*Struct2)
}
// Continue with 'a' only
a.Param = 15
fmt.Println(a.String())
Go is a statically typed language, the type of a must be known at compile time. And since Go does not support generics yet, you can't do what you want.
Try to come up with some other solution, e.g. abstract away the things you want to do with a into an interface, and have the concrete types implement that interface. Then a can be a variable of this interface type, and you can call methods of it.
If you can achieve this, actually you can even change the parameter of the data type to this interface, and no type assertion or type switch is needed.
Alternatively you could use reflection to access common fields (either for get or set) identified by their name, but reflection provides no compile-time guarantee, and it's usually less efficient. For an example how to do that, see this question: Assert interface to its type
You can't do what you ask for in your question directly, go is statically typed, so you can't have one variable that can hold different types, and still access that variable as if it is typed.
If you're only working on the common struct fields in your method, you are perhaps better off gathering all the common variables in its own struct, illustrated below as the commons struct and have your method take that type as an argument
package main
import (
"fmt"
)
type commons struct {
name string
age int
}
type structA struct {
commons
other_stuff int
}
type structB struct {
commons
foo string
}
func method(c* commons) {
fmt.Println(c)
c.age +=1
}
func main() {
a := structA{commons{"foo", 44}, 1}
b := structB{commons{"bar", 33}, "test"}
method(&a.commons)
method(&b.commons)
fmt.Println(a)
}
Go playground
I can't figure out what is your real goal but if the "method" you want to write handles common fields from similar structures, and you cannot fix original structures using Type Embedding, as #nos said above, then you can try to make another structure for method-internal use:
var v Vehicle // with common fields
switch data.(type) {
case *Car:
v.Handle = data.(*Car).Handle // or CircleHandle
case *Motorcycle:
v.Handle = data.(*Motorcycle).Handle // or BarHandle
}
v.Degree = 15
v.Speed = 50
v.Direction = "left"
v.Style = "rough"
/// so many things on `v`...
steering(v)
I think it is not a good approach but sometimes... :-)
I have a function which takes an interface, like this:
func method(data interface{})
.. because I need to process different structs which have common fields/methods. In this function I use data tens or hundreds of times, in different places. It's really unpleasant to add switch a.(type) { case .. case .. all the time.
Is there a way to create a variable with just one switch with needed type and then just use this variable everywhere later? Something like:
var a .... // something here
switch data.(type) {
case *Struct1:
a = data.(*Struct1)
case *Struct2:
a = data.(*Struct2)
}
// Continue with 'a' only
a.Param = 15
fmt.Println(a.String())
Go is a statically typed language, the type of a must be known at compile time. And since Go does not support generics yet, you can't do what you want.
Try to come up with some other solution, e.g. abstract away the things you want to do with a into an interface, and have the concrete types implement that interface. Then a can be a variable of this interface type, and you can call methods of it.
If you can achieve this, actually you can even change the parameter of the data type to this interface, and no type assertion or type switch is needed.
Alternatively you could use reflection to access common fields (either for get or set) identified by their name, but reflection provides no compile-time guarantee, and it's usually less efficient. For an example how to do that, see this question: Assert interface to its type
You can't do what you ask for in your question directly, go is statically typed, so you can't have one variable that can hold different types, and still access that variable as if it is typed.
If you're only working on the common struct fields in your method, you are perhaps better off gathering all the common variables in its own struct, illustrated below as the commons struct and have your method take that type as an argument
package main
import (
"fmt"
)
type commons struct {
name string
age int
}
type structA struct {
commons
other_stuff int
}
type structB struct {
commons
foo string
}
func method(c* commons) {
fmt.Println(c)
c.age +=1
}
func main() {
a := structA{commons{"foo", 44}, 1}
b := structB{commons{"bar", 33}, "test"}
method(&a.commons)
method(&b.commons)
fmt.Println(a)
}
Go playground
I can't figure out what is your real goal but if the "method" you want to write handles common fields from similar structures, and you cannot fix original structures using Type Embedding, as #nos said above, then you can try to make another structure for method-internal use:
var v Vehicle // with common fields
switch data.(type) {
case *Car:
v.Handle = data.(*Car).Handle // or CircleHandle
case *Motorcycle:
v.Handle = data.(*Motorcycle).Handle // or BarHandle
}
v.Degree = 15
v.Speed = 50
v.Direction = "left"
v.Style = "rough"
/// so many things on `v`...
steering(v)
I think it is not a good approach but sometimes... :-)
Scenario:
I have a few different clients, each interacting with a different API.
The data fields of these clients are the same:
type clientX struct {
key string
secret string
client *http.Client
}
However these clients each have many methods (all different from each other):
func (c *ClientX) someMethod() (*ResponseType, error) {
//code
}
The amount of clients may change over time, as support for new APIs is added, or some number of APIs go offline. Therefore, all functions in the main package need to be modular and adaptable to accept a variable number of clients as arguments.
What is the best way to go about this problem?
I can't put the clients in an array because they are different types.
Ideas I'm toying around with:
The first solution that comes to mind is an array of type interface{}. However I'm concerned of the performance of an []interface{} as well as the code-bloat I'll have from identifying client types when iterating through the array (type-assertions).
I'm not as educated on inheritance as I'd like to be, so I'm not sure if this works. I'm envisioning creating a parent class Client containing the key, secret, and client data fields. The specific clients will be subclasses inheriting from the parent class Client, and then defining all the methods specific to that client. From my basic understanding, I could then put all of these clients into an array by defining the array type as Client. This leaves me a bit confused on how the elements in the array would behave as the would not be of type ClientX but of the more general type Client. Would this lead to having to type assert all over again aka the same problem as in solution 1? If Im going to have to ID and assert the type anyway are there any performance benefits to having an array of type Client over an array of type interface?
Have the clients (clientA, clientB, clientC) be global variables. Any function can access them so I won't have to pass them as arguments. In order to handle variable clients (the number is decided at runtime) I would have a clientsEnabled map[string]bool for functions to identify which clients to use and which to ignore. This seems like it would have minimal code-bloat. However, I'm wary of using globals, and was always taught to avoid unless absolutely necessary.
Another solution that the SO community has
Would love to have some feedback, thank you.
First of, there is no inheritance in golang. Also, I'd highly recommend reading about interfaces in golang.
As for this problem specifically, instead of storing interface{} instances, I'd introduce a command interface and implement it for each API with which the application would have to work. Something like this: https://play.golang.org/p/t5Kldpbu-P.
Since you mentioned that there is no common behaviour amongst the client commands, I wouldn't introduce interfaces for their methods unless there are inter-dependencies amongst them. Interfaces in that case would make them easy to unit test (create a mock that implements the interface).
This is simple and easy to extend.
From the information given, it sounds like you should define an interface type that encapsulates what the various client types have in common. That would be the way to actually achieve what you talk about in #2. Remember that Go does not have the concept of classes and subclasses, so if you have a type ClientX and then embed that in other types (the closest thing Go has to subclassing), those other types cannot be used where a type ClientX is expected. The only way to have one type that can represent several different underlying types is by defining an interface.
In addition to the common fields in the ClientX struct, I assume you will have to have some sort of client-specific handler function. That function would then do whatever client-specific operations are necessary. (It's hard to be more specific without knowing more details about what you're doing.)
Here's a simple example:
package main
import (
"fmt"
"net/http"
)
type client interface {
getKey() string
getSecret() string
getHttpClient() *http.Client
handler()
}
type clientX struct {
key string
secret string
client *http.Client
}
func (c *clientX) getKey() string {
return c.key
}
func (c *clientX) getSecret() string {
return c.secret
}
func (c *clientX) getHttpClient() *http.Client {
return c.client
}
type clientOne struct {
clientX
data1 string
data2 int
// ...
}
func (c *clientOne) handler() {
fmt.Printf("clientOne handler: data1: %q\n", c.data1)
}
func main() {
c1 := &clientOne{
clientX: clientX{
key: "abc",
secret: "def",
},
data1: "some data",
}
var clients []client
clients = append(clients, c1)
for _, c := range clients {
fmt.Printf("key %q secret %q\n", c.getKey(), c.getSecret())
c.handler()
}
}
I'm currently in the design stage of writing a utility library that will make interaction with the x-go-binding a bit easier. (I've done this before with Python and xpyb.) For example, it will help with querying information defined in the EWMH spec and binding keys to callback functions. (And much more.) So as my initial idea for a package layout, consider:
xutil
ewmh
keybind
Where each is its own package. (Similar to how the standard library's image package is setup.)
What's unique about my situation is that almost every x-go-binding call requires some combination of an xgb connection object or a root window identifier. Therefore, it makes sense to me to store this information in a struct like so:
type XUtilConnection struct {
conn xgb.Conn
root xgb.Id
// a few other things, like a mapping of events to callbacks
}
So that I'd have a factory that could be used like so:
xconn = xutil.NewXUtilConnection(blah blah)
And it could be used like:
xconn.get_active_window()
xconn.bind_key("Shift-a", my_callback_fun)
There may also be functions like:
keybind.get_keycode("a")
ewmh.get_atom("_NET_ACTIVE_WINDOW")
My problem of course is that receivers, to my knowledge, can only be of types that have been declared in the same package. If I separate my packages, I cannot use my XUtilConnection type as a receiver in any of my sub-packages.
I suspect that my answer is going to be making this one big package separated into different logical files, but I fear that this might lead to namespace clutter. (For example, implementing the EWMH spec is probably on the order of 100+ functions.)
I am also aware that I could define a new container type in each sub-package for my XUtilConnection object. (I've heard that this should be a struct containing a single member XUtilConnection to avoid casting.) But this seems like a really messy situation to me, and would prevent the kind of semantics I'd like. (i.e., using an XUtilConnection struct to call methods in several different modules.)
I would suggest to use embedding.
In package xutil:
type XUtilConnection struct {
*ewmh.EWMH // Embed all methods of *ewmh.EWMH
*keybind.KeyBind // Embed all methods of *keybind.KeyBind
}
In package xutil/ewmh:
type EWMH struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some EWMH methods:
func (e *EWMH) GetAtom(name string) { ... }
func (e *EWMH) ...
In package xutil/keybind:
type KeyBind struct {
Conn xgb.Conn
Root xgb.Id
// and any additional fields that are needed
}
// Some keybind methods:
func (k *KeyBind) GetKeyCode(s string) { ... }
func (k *KeyBind) ...
This will enable you to directly call EWMH's and KeyBind's methods on values of type *XUtilConnection:
var c *XUtilConnection = ...
c.GetAtom("_NET_ACTIVE_WINDOW") // Call (*emwh.EWMH).GetAtom(string)
c.GetKeyCode("a") // Call (*keybind.KeyBind).GetKeyCode(string)
I'm not sure if I understood correctly the problem (I'm confused by seeing package names where they seem to be discussed as method receivers?), but I guess passing around an interface instead of the [*]struct would enable satisfying it from within any package. One can also always do something like (totally untested code):
package foo
type Foo interface { Bar(); Baz() }
----
package qux
import "foo"
type qux struct { foo.Foo; myStuff t }
func Foo(f foo.Foo) foo.Foo {
return qux{f, &t{}}
}
func (q qux) Bar() {
// smthg
}
To e.g. "override" f.Bar in package qux and "inherit" f.Baz() unaltered.