How is actually methods in Go get dispatched if we use interface, static(compile time) or dynamic(run time). Let consider this code:
package main
import "fmt"
type ICat interface {
Meow()
Walk()
Run()
}
func NewCat(name string) ICat {
return &cat{
name:name,
}
}
type cat struct {
name string
}
func (c *cat) Meow() {
fmt.Print("Meowwwwwwwww")
}
func (c *cat) Walk() {
fmt.Print("Walk")
}
func (c *cat) Run() {
fmt.Print("Run")
}
type IAnimal interface{
DoSound()
}
type animal struct {
cat ICat
}
func New() IAnimal {
return &animal{
cat:NewCat("bobby"),
}
}
func (a *animal) DoSound() {
a.cat.Meow()
}
func main() {
i := New()
i.DoSound()
}
Go Playground: https://play.golang.org/p/RzipDT6FAC9
How actually those methods defined in those interface got dispatched?, I use this style of development to implement interface segregation and separation of concern between data and behaviour. My other concern is the perf. Some said it's statically dispatched at compile time, while other said it's dynamically dispatched at run time.
We cannot know at compile time what the dynamic type of an interface value will be, A call through an interface must use dynamic dispatch. Instead of a direct call, the compiler must generate code to obtain the address of the method from the type descriptor, then make an indirect call to that address.
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 appears to be a duplicate of Can embedded methods access "parent" fields?, but it is not in the sense that I know that there is no way to access the "parent" fields; I am just looking for suggestions on another way to do this, because I like the idea of the Pausable struct.
I am trying to make a convenience struct that enables other structs to receive some pausing/unpausing methods.
Imagine the following:
Pausable struct
type Pausable struct {
isPaused bool
}
func (p *Pausable) Pause() {
p.isPaused = true
}
func (p *Pausable) Unpause() {
p.isPaused = false
}
Struct that composes with Pausable
Now on my other struct I want to overwrite the Unpause() method, so that besides changing the value of p.isPaused some other stuff happens as well.
type Mystruct struct {
Pausable // Composition
}
func (s *Mystruct) Unpause() {
s.Unpause()
// Do other stuff
}
Problem
The problem becomes this. I want to add an PauseUntil() method to the Pausable struct, so that it becomes
type Pausable struct {
isPaused bool
}
func (p *Pausable) Pause() {
p.isPaused = true
}
func (p *Pausable) Unpause() {
p.isPaused = false
}
func (p *Pausable) PauseUntil(dur time.Duration) {
p.Pause()
go func() {
time.Sleep(dur)
p.Unpause()
}()
}
When the timeout runs out, however, Unpause() is called on Pausable, and not on Mystruct. What would be a clever way around this?
You could make PauseUntil a function that operates on a Pauser interface.
E.g.
type Pauser interface {
Pause()
Unpause()
}
func PauseUntil(p Pauser) {
p.Pause()
go func() {
time.Sleep(dur)
p.Unpause()
}()
}
Then you should be able to pass your myStruct to that function:
ms := new(myStruct)
PauseUntil(ms)
I am using pagerduty go sdk to do a bunch of api requests.
Particularly I am making use of
func NewClient(authToken string) *Client
to create a new Client type. I want to add some utility functions to my own work to *Client. I tried doing this:
type BetterPdClient *pagerduty.Client
func NewClient(auth string) BetterPdClient {
return pagerduty.NewClient(auth)
}
func (b *BetterPdClient) DoSomething() {
b.GetIncident(....)
}
func main() {
pd_client := NewClient("")
fmt.Println(pd_client)
pd_client.DoSomething()
}
But I get the following error:
invalid receiver type *BetterPdClient (BetterPdClient is a pointer type)
I understand that DoSomething() is expecting a pointer as caller. Only other way I could think of is sending the ptr as a function argument:
func NewClient(auth string) *pagerduty.Client {
return pagerduty.NewClient(auth)
}
func DoSomething(cl *pagerduty.Client) {
fmt.Println(cl)
}
func main() {
pd_client := NewClient("")
fmt.Println(pd_client)
DoSomething(pd_client)
}
Is there a better way?
Declaring a type as a pointer to another type is almost never what you want because Go doesn't allow you to add methods to that new type, nor to the pointer of that type as you've already figured out yourself. This one doesn't compile either:
type T struct{}
type P *T
func (P) M() {}
If you want to "extend" a type without "hiding" it's existing functionality your best bet is to embed it in a struct.
type T struct{
// ...
}
func (T) M() {}
type U struct {
*T
}
func NewU() *U {
return &U{&T{}}
}
func (U) N() {}
func main() {
u := NewU()
u.M()
u.N()
}
And what I mean by "hiding existing functionality" is that when you define a new type in terms of another, already existing type, your new type will not get direct access to the methods of the existing type. All you're doing is just saying that your new type should have the same structure as the already existing type. Although it's worth pointing out that this property gives you the ability to convert one type to the other...
type T struct{
// ...
}
func (T) M() {}
type U T
func NewU() *U {
return &U{}
}
func (U) N() {}
func main() {
u := NewU()
u.M() // compile error
u.N()
// convert *U to *T and then call M
(*T)(u).M()
}
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