Is there exists some trick to implement virtual functions behaviour in go ? I have the following example.
package main
import "fmt"
type A struct {
}
type B struct {
*A
}
func (this *A) Do() {
fmt.Println("IM DO")
this.DoVirtual()
}
func (this *A) DoVirtual() {
fmt.Println("IM DoVirtual Default implementation")
}
func (this *B) DoVirtual() {
fmt.Println("IM DoVirtual B implementation")
}
func main() {
a := &A{}
a.Do()
fmt.Println("----")
b := &B{}
b.DoVirtual()
b.Do() // How to make here B.DoVirtual call
}
And the last Do() call uses also default DoVirtual implementation what is actually not was I want. The reason why is it so is go lang iheritance model : this *B and this *A are different pointers in this case, but I wonder is it possible to make some simulation of such behaviour that DoVirtual in last call will be used from B class.
By the time the compiler has selected func (this *A) Do() { the enclosing B is gone, no longer accessible. Go does not support the is-a construct, only the has-a (composition). If one implements a func (this *B) Do() { it will supersede the Do() on *A. Of course, that's not really what you are wanting.
I think the best explanation of the implementation and motivation is here Less is exponentially more from Rob Pike.
my simple simulation, you can improve it with some reflect, code generation or even RPC. the main idea is add a virtual method table, and do dispatch yourself, just like c++ does.
package main
import "fmt"
type A struct {
virFunDispatcher func(funAndParams ... interface{})
}
func newA() *A{
return &A{func(funAndParams ... interface{}){
fun := funAndParams[0].(string)
switch(fun){
case "DoVirtual":
fmt.Println("IM DoVirtual Default implementation")
}
}}
}
type B struct {
*A
}
func newB() *B{
a := A{func(funAndParams ... interface{}){
fun := funAndParams[0].(string)
switch(fun){
case "DoVirtual":
fmt.Println("IM DoVirtual B implementation")
}
}}
return &B{&a}
}
func (this *A) Do() {
fmt.Println("IM DO")
this.virFunDispatcher("DoVirtual")
}
func (this *A) DoVirtual() {
fmt.Println("IM DoVirtual Default implementation")
}
func (this *B) DoVirtual() {
fmt.Println("IM DoVirtual B implementation")
}
func main() {
a := newA()
a.Do()
fmt.Println("----")
b := newB()
b.DoVirtual()
b.Do() // How to make here B.DoVirtual call
}
https://play.golang.org/p/Iw30lVOhuC
Related
I have a struct like so,
//
// HandlerInfo is used by features in order to register a gateway handler
type HandlerInfo struct {
Fn func(interface{})
FnName string
FnRm func()
}
where I want to pass a func:
func StarboardReactionHandler(e *gateway.MessageReactionAddEvent) {
// foo
}
i := HandlerInfo{Fn: StarboardReactionHandler}
Unfortunately, this results in:
Cannot use 'StarboardReactionHandler' (type func(e *gateway.MessageReactionAddEvent)) as the type func(interface{})
I found this workaround:
func StarboardReactionHandler(e *gateway.MessageReactionAddEvent) {
// foo
}
func handlerCast(e interface{}) {
StarboardReactionHandler(e.(*gateway.MessageReactionAddEvent))
}
i := HandlerInfo{Fn: handlerCast}
Is there some way that I can simplify needing handlerCast, such as doing it inside my StarboardReactionHandler or in HandlerInfo? Maybe with generics or reflection? I basically just want to minimize the syntax / boilerplate that's required here.
you can use interface{}.(type)
follow is a exmple:
package main
import "fmt"
type HandlerInfo struct {
Fn func(interface{})
FnName string
FnRm func()
}
type MessageReactionAddEvent = func(a, b int) int
func StarboardReactionHandler(e interface{}) {
switch e.(type) {
case MessageReactionAddEvent:
fmt.Printf("%v\n", (e.(MessageReactionAddEvent))(1, 2))
}
}
func add(a, b int) int {
return a + b
}
func main() {
i := HandlerInfo{Fn: StarboardReactionHandler}
i.Fn(add)
}
How to implement an abstract class in Go? As Go doesn't allow us to have fields in interfaces, that would be a stateless object. So, in other words, is it possible to have some kind of default implementation for a method in Go?
Consider an example:
type Daemon interface {
start(time.Duration)
doWork()
}
func (daemon *Daemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
daemon.doWork()
}
}()
}
type ConcreteDaemonA struct { foo int }
type ConcreteDaemonB struct { bar int }
func (daemon *ConcreteDaemonA) doWork() {
daemon.foo++
fmt.Println("A: ", daemon.foo)
}
func (daemon *ConcreteDaemonB) doWork() {
daemon.bar--
fmt.Println("B: ", daemon.bar)
}
func main() {
dA := new(ConcreteDaemonA)
dB := new(ConcreteDaemonB)
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
time.Sleep(100 * time.Second)
}
This won't compile as it's not possible to use interface as a receiver.
In fact, I have already answered my question (see the answer below). However, is it an idiomatic way to implement such logic? Are there any reasons not to have a default implementation besides language's simplicity?
The other answers provide an alternative to your problem, however they proposed solution without using abstract classes/struct, and I guess if you were interested in using abstract class like solution, here is very precise solution to your problem:
Go plaground
package main
import (
"fmt"
"time"
)
type Daemon interface {
start(time.Duration)
doWork()
}
type AbstractDaemon struct {
Daemon
}
func (a *AbstractDaemon) start(duration time.Duration) {
ticker := time.NewTicker(duration)
// this will call daemon.doWork() periodically
go func() {
for {
<- ticker.C
a.doWork()
}
}()
}
type ConcreteDaemonA struct {
*AbstractDaemon
foo int
}
func newConcreteDaemonA() *ConcreteDaemonA {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonA{a, 0}
a.Daemon = r
return r
}
type ConcreteDaemonB struct {
*AbstractDaemon
bar int
}
func newConcreteDaemonB() *ConcreteDaemonB {
a:=&AbstractDaemon{}
r:=&ConcreteDaemonB{a, 0}
a.Daemon = r
return r
}
func (a *ConcreteDaemonA) doWork() {
a.foo++
fmt.Println("A: ", a.foo)
}
func (b *ConcreteDaemonB) doWork() {
b.bar--
fmt.Println("B: ", b.bar)
}
func main() {
var dA Daemon = newConcreteDaemonA()
var dB Daemon = newConcreteDaemonB()
dA.start(1 * time.Second)
dB.start(5 * time.Second)
time.Sleep(100 * time.Second)
}
If this is still not obvious how to use abstract classes/multi-inheritance in go-lang here is the post with comprehensive details. Abstract Classes In Go
If you want to provide a "default" implementation (for Daemon.start()), that is not the characteristic of an interface (at least not in Go). That is a characteristic of a concrete (non-interface) type.
So Daemon in your case should be a concrete type, conveniently a struct since you want it to have fields. And the task to be done can be either a value of an interface type, or in a simple case just a function value (a simple case means it would only have one method).
With interface type
Try the complete app on the Go Playground.
type Task interface {
doWork()
}
type Daemon struct {
task Task
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task.doWork() periodically
go func() {
for {
<-ticker.C
d.task.doWork()
}
}()
}
type MyTask struct{}
func (m MyTask) doWork() {
fmt.Println("Doing my work")
}
func main() {
d := Daemon{task: MyTask{}}
d.start(time.Millisecond*300)
time.Sleep(time.Second * 2)
}
With a function value
In this simple case this one is shorter. Try it on the Go Playground.
type Daemon struct {
task func()
}
func (d *Daemon) start(t time.Duration) {
ticker := time.NewTicker(t)
// this will call task() periodically
go func() {
for {
<-ticker.C
d.task()
}
}()
}
func main() {
d := Daemon{task: func() {
fmt.Println("Doing my work")
}}
d.start(time.Millisecond * 300)
time.Sleep(time.Second * 2)
}
An easy solution is to move daemon *Daemon to the argument list (thus removing start(...) from the interface):
type Daemon interface {
// start(time.Duration)
doWork()
}
func start(daemon Daemon, duration time.Duration) { ... }
func main() {
...
start(dA, 1 * time.Second)
start(dB, 5 * time.Second)
...
}
You can implement abstract class in go.
The definition:
type abstractObject interface{
print()
}
type object struct{
a int
abstractObject
}
Now object is an abstract class, like java's.
You can inherit it and use its members:
type concreteObject struct{
*object
}
(o *concreteObject) print() {
fmt.Println(o.a)
}
func newConcreteObject(o *object) {
obj := &concreteObject{object: o}
o.abstractObject = obj // all magics are in this statement.
}
And use the object with concreteObject's methods:
o := &object{}
newConcereteObject(o)
o.print()
And cast abstract object to concrete object:
concObj := o.abstractObject.(*concreteObject)
Just like other OOP languages.
The solution by Max Malysh would work in some cases if you don't need a factory. However the solution given by Adrian Witas could cause cyclic dependencies issues.
This is the way I achieved implementing an abstract class the easy way respecting cyclic dependencies and good factory patterns.
Let us assume we have the following package structure for our component
component
base
types.go
abstract.go
impl1
impl.go
impl2
impl.go
types.go
factory.go
Define the definition of the component, in this example it will be defined here:
component/types.go
package component
type IComponent interface{
B() int
A() int
Sum() int
Average() int
}
Now let's assume we want to create an abstract class that implements Sum and Average only, but in this abstract implementation we would like to have access to use the values returned by the implemented A and B
To achieve this, we should define another interface for the abstract members of the abstract implementation
component/base/types.go
package base
type IAbstractComponentMembers {
A() int
B() int
}
And then we can proceed to implement the abstract "class"
component/base/abstract.go
package base
type AbstractComponent struct {
IAbstractComponentsMember
}
func (a *AbstractComponent) Sum() int {
return a.A() + a.B()
}
func (a *AbstractComponent) Average() int {
return a.Sum() / 2
}
And now we proceed to the implementations
component/impl1/impl.go // Asume something similar for impl2
package impl1
type ComponentImpl1 struct {
base.AbstractComponent
}
func (c *ComponentImpl1) A() int {
return 2
}
func (c *ComponentImpl1) A() int {
return 4
}
// Here is how we would build this component
func New() *ComponentImpl1 {
impl1 := &ComponentImpl1{}
abs:=&base.AbstractComponent{
IAbstractComponentsMember: impl1,
}
impl1.AbstractComponent = abs
return impl1
}
The reason we use a separate interface for this instead of using Adrian Witas example, is because if we use the same interface in this case, if we import the base package in impl* to use the abstract "class" and also we import the impl* packages in the components package, so the factory can register them, we'll find a circular reference.
So we could have a factory implementation like this
component/factory.go
package component
// Default component implementation to use
const defaultName = "impl1"
var instance *Factory
type Factory struct {
// Map of constructors for the components
ctors map[string]func() IComponent
}
func (f *factory) New() IComponent {
ret, _ := f.Create(defaultName)
return ret
}
func (f *factory) Create(name string) (IComponent, error) {
ctor, ok := f.ctors[name]
if !ok {
return nil, errors.New("component not found")
}
return ctor(), nil
}
func (f *factory) Register(name string, constructor func() IComponent) {
f.ctors[name] = constructor
}
func Factory() *Factory {
if instance == nil {
instance = &factory{ctors: map[string]func() IComponent{}}
}
return instance
}
// Here we register the implementations in the factory
func init() {
Factory().Register("impl1", func() IComponent { return impl1.New() })
Factory().Register("impl2", func() IComponent { return impl2.New() })
}
The functionality of abstract class has below requirements
1. It should not be possible to create direct instance of abstract class
2. It should provide default fields and methods.
A combination of interface and struct can be used to fulfill above two requirements. For example we can see below
package main
import "fmt"
//Abstract Interface
type iAlpha interface {
work()
common(iAlpha)
}
//Abstract Concrete Type
type alpha struct {
name string
}
func (a *alpha) common(i iAlpha) {
fmt.Println("common called")
i.work()
}
//Implementing Type
type beta struct {
alpha
}
func (b *beta) work() {
fmt.Println("work called")
fmt.Printf("Name is %s\n", b.name)
}
func main() {
a := alpha{name: "test"}
b := &beta{alpha: a}
b.common(b)
}
Output:
common called
work called
Name is test
One important point to mention here is that all default method should have iAlpha as first argument, and if default method needs to call any unimplemented method they they will call on this interface. This is same as we did in common method above - i.work().
Source: https://golangbyexample.com/go-abstract-class/
This question is about the cleanest way to "inherit" interface implementations in golang. I understand Go does not have inheritance; this question is about how people achieve it otherwise, hence the quotes around inheritance.
Let's say theres a standard library interface defined, for example container/heap: https://golang.org/pkg/container/heap/#Interface
Lets say there's a .go file called pq.go that implements that interface:
//pq.go
import ("container/heap")
type PriorityQueue []*Vertex
func (pq PriorityQueue) Len() int { return len(pq) }
func (pq PriorityQueue) Less(i, j int) bool {
...
}
func (pq PriorityQueue) Swap(i, j int) {
...
}
func (pq *PriorityQueue) Push(x interface{}) {
...
}
func (pq *PriorityQueue) Pop() interface{} {
...
}
Now let's say I just want a Tiny variant on this, called MaxPQ, in maxpq.go, for where I want to override a single implementation detail of pq.go, e.g., override Less(..). How do I achieve this without literally copying the last file over, changing the type name, and changing the implementation of the single function, e.g., less?
Meaning, is there a way to make a new implementation of an interface that is very similar to another?
Doing this, literally copying it over, seems drastic and changes would need to be made in multiple places:
//maxpq.go
import ("container/heap")
type MaxPriorityQueue []*Vertex
func (pq MaxPriorityQueue) Len() int { return len(pq) }
func (pq MaxPriorityQueue) Less(i, j int) bool {
...
}
func (pq MaxPriorityQueue) Swap(i, j int) {
...
}
func (pq *MaxPriorityQueue) Push(x interface{}) {
...
}
func (pq *MaxPriorityQueue) Pop() interface{} {
...
}
There are multiple ways you can do this.
You can define a new type based on the original type, and delegate all methods:
type OriginalType struct {...}
func (o OriginalType) F() {...}
type NewType OriginalType
func (n NewType) F() { OriginalType(n).F() }
With this, you need to redefine all methods of the original type, as the NewType does not "inherit" the methods of the OriginalType.
You can embed:
type NewType struct {
OldType
}
Now you have a NewType.F() function, but it will operate on the OldType portion of the NewType. If you want to redeclare that, you can:
func (n NewType) F() {
n.OldType.F();
// Do more stuff
}
This will work like inheritance if you pass either instance through an interface. That is:
type IntF interface {
F()
}
func f(v IntF) {
v.F()
}
If you pass a NewType, then NewType.F will be called.
However, you have to pass an interface, you cannot pass the embedded struct to get the behavior of the enclosing object:
func f(v OriginalType) {
v.F()
}
func main() {
n:=NewType()
// f(n) Won't work
f(n.OriginalType)
Above, only the OriginalType part of n is sent to the function f, and OriginalType.F will be called.
You can try something like this using composition.
type iTemp interface {
func1()
func2()
}
type base struct {
}
func (base) func1() {
fmt.Println("base func1")
}
func (base) func2() {
fmt.Println("base func2")
}
type child struct {
base
}
func (child) func1() {
fmt.Println("child func1")
}
func main(){
printMessage(base{})
printMessage(child{})
}
func printMessage(t iTemp) {
t.func1()
t.func2()
}
output:
base func1
base func2
child func1
base func2
Here in child struct you are providing a new implementation of func1 function of base class, but you still have access to base class implementation, you can still call it using child{}.base.func1()
I'm modeling the state machine implementation outlined in this talk by Rob Pike https://www.youtube.com/watch?v=HxaD_trXwRE&t=1830s
and I'm not able to get it to compile. I've provided a small sample that fails.
The call: m := New(foo)
fails with
./main.go:31:11: undefined: foo
I've tried
m := New(M.foo)
m := New(foo(*M))
I don't know the proper syntax for this.
package main
type StateFunc func(*M) StateFunc
type M struct {
start StateFunc
}
func New(start StateFunc) *M {
return &M{
start: start,
}
}
func (m *M) foo() StateFunc {
return nil
}
func (m *M) Start() {
go m.run()
}
func (m *M) run() {
state := m.start
for state != nil {
state = state(m)
}
}
func main() {
m := New(foo)
}
I would expect it to compile but I don't know the proper syntax to make this work.
the method (m *M) foo() doesn't match the signature of type StateFunc func(*M) StateFunc
foo is a method, it has a receiver *M, you can't use it without the receiver.
my suggestion is to modify foo:
func foo(*M) StateFunc {
return nil
}
There is func someFunc(v interface{}, fn interface{}) where v is a pointer to struct (say *A) and fn is a method expression (say (*A).method()). How to call fn with v as parameter (using reflect)?
It's possible to do with reflect.Value.Call(), however it's pretty cumbersome, especially if you need to do something with the return value. But here's a basic example:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
Bar string
}
func concrete(foo *Foo) {
fmt.Printf("Foo: %#v\n", foo)
}
func someFunc(v interface{}, fn interface{}) {
f := reflect.ValueOf(fn)
arg := reflect.ValueOf(v)
f.Call([]reflect.Value{arg})
}
func main() {
foo := Foo{"Bar"}
someFunc(&foo, concrete)
}
// Output: Foo: &main.Foo{Bar:"Bar"}
https://play.golang.org/p/ED6QdvENxti
If you want to call a method of a struct by name, we need to revise it just a bit:
type Foo struct {
Bar string
}
func (f *Foo) Concrete() {
fmt.Printf("Foo: %#v\n", f)
}
func callByName(v interface{}, fn string) {
arg := reflect.ValueOf(v)
f := arg.MethodByName(fn)
f.Call([]reflect.Value{})
}
func main() {
foo := Foo{"Bar"}
callByName(&foo, "Concrete")
}
Notice that in this case the method value is already bound to the struct instance, so we don't need to pass it anything as an argument.
So to the challenge of using reflect to call a method without knowing name and being a method of the same type, as op (orignally) addressed, I have come up with a very, very ugly and unsafe way.
package main
import (
"fmt"
"reflect"
"runtime"
"strings"
)
func getFName(v reflect.Value) string {
return runtime.FuncForPC(v.Pointer()).Name()
}
func callMethod(a,fn interface{}) {
fname:=getFName(reflect.ValueOf(fn))
parts:=strings.Split(fname,".")
name:=strings.TrimSuffix(parts[len(parts)-1],"-fm")
reflect.ValueOf(a).MethodByName(name).Call(nil)
}
func (s *a) Tst() {
fmt.Println(s)
}
type a struct { p string }
func main() {
x,y:=a{"Good"},a{"Bad"}
callMethod(&x,y.Tst)
}
Playground: https://play.golang.org/p/QgrGhI5DC3p
I would like to know a better way that does not rely on how runtime.FuncForPc formats methods (which is not version-safe), but this is the best I have. Please do tell me any ideas to improve it.