Question about the method invoked by the base struct

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.

In Go, the method receiver is not special, there is no practical difference between

func (t *foo) PrintMsg()

and

func PrintMsg(t *foo)

In fact this exactly what is happening behind the scenes, the compiler rewrites “method” calls to the comparable function calls.

When you look at it this way, it is clear that there is no way for PrintMsg(t *foo) to ever call *bar's Msg function as it only has access to a *foo.

1 Like

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

Thanks your reply, this is exactly what the spec says.

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.

If you create your own myfoo type, return is mybar like in https://play.golang.org/p/fXmWRGBDPt

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.