package main
import "fmt"
type foo struct {
msg string
}
func (t *foo) Msg() string {
return "from foo"
}
func (t *foo) PrintMsg() {
//should invoke *bar.Msg here
fmt.Println(t.Msg())
}
type bar struct {
foo
}
func (t *bar) Msg() string {
return t.msg
}
func main() {
b := new(bar)
b.msg = "from bar"
b.PrintMsg()
}
//output: from foo
In the above piece of code, I invoke the method *bar.PrintMsg, which invokes the method *bar(or *foo).Msg, and the output is from foo, not from bar as expected.
Below is a python counterpart of the above Go code, and the output is what I expect.
class foo(object):
def __init__(self, msg):
self.msg = msg
def Msg(self):
return "from foo"
def printmsg(self):
print(self.Msg())
class bar(foo):
def __init__(self, msg):
super(bar, self).__init__(msg)
self.msg = msg
def Msg(self):
return self.msg
t1 = bar("from bar")
t1.printmsg()
#output: from bar
Is there any explanation about the output of the Go code considering the language specification or the implementation of struct combination?
I am not a native English speaker, so I’m wondering whether I explained myself clearly.
Maybe another part of the question is that the type inheritance is foo when reaching PrintMsg when it is bar elsewhere. If you consider the output of
fmt.Println(“From assignment :”,b.msg)
fmt.Println(“From Msg method :”,b.Msg())
b.PrintMsg()
provides
From assignment : from bar
From Msg method : from bar
from PrintMsg : from foo
Actually I have this kind of code in one of my web applications:
package main
type foo1 struct {
foo
}
type foo2 struct {
foo
}
//type foo3
//type fooN
//...
//The struct foo implements fooInterface.
//Every fooN embeds foo, so they automatically implement fooInterface.
type fooInterface interface {
PrintMsg() string
}
//Here in this function, I may get foo or fooN or non-foo as its parameter
//And then I do a type assertion here and call its PrintMsg method if the interface is a fooInterface.
//In the method PrintMsg, many other methods of foo will be called.
//If every fooN calls the foo's methods, I find it kind of redundant to write a PrintMsg method for every fooN.
//This is but a very simple PrintMsg, in the real case it may be a very big one with tens or hundreds of lines.
func SomeFunc(SomeInterface interface{}) {
if f, ok := SomeInterface.(fooInterface); ok {
f.PrintMsg()
}
//do some other things
}
Now I realy write a PrintMsg method for every fooN.