Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Go, how can I get the TypeOf a type using an anonymous field method?

Tags:

go

How do I get the correct Type of the struct using the anonymous field (or superclass)?

I am trying to make this fish describe itself as a cod:

package main

import (
    "fmt"
    "reflect"
)

type Fish struct {
}

func (self *Fish) WhatAmI() string {
    return reflect.TypeOf(self).String()
}

type Cod struct {
    Fish
}

func main() {
    c := new(Cod)
    fmt.Println("I am a", c.WhatAmI())
}

The output I get is:

I am a *main.Fish

What I want is:

I am a *main.Cod
like image 487
This statement is false Avatar asked Jun 04 '13 11:06

This statement is false


2 Answers

You are getting the correct answer. The answer you want to get is wrong.

In

func (f *Fish) WhatAmI() string {
        return reflect.TypeOf(f).String()
}

f is of type *main.Fish, it's even declared to be of that type (f *Fish). Thus it cannot ever be of type *main.Cod.

The probable source of confusion: The method set of Cod inherites the method set of its embedded, anonymous field Fish and doesn't override it. Thus invoking WhatAmI on an instance of Cod "delegates" the call to Fish.WhatAmI, but the receiver is now the embedded field of type *main.Fish.

Example with overriding the inherited method:

package main

import (
        "fmt"
)

type Fish struct {
}

func (f *Fish) WhatAmI() string {
        return fmt.Sprintf("%T", f)
}

type Cod struct {
        Fish
}

func (c *Cod) WhatAmI() string {
        return fmt.Sprintf("%T", c)
}

func main() {
        c := new(Cod)
        fmt.Println("I am a", c.WhatAmI())
}

Playground


Output:

I am a *main.Cod
like image 98
zzzz Avatar answered Nov 07 '22 21:11

zzzz


For a fairly generic solution, you could separate the WhatAmI function from the Fish type and use an empty interface (see Andrew Gerrand's "The Laws of Reflection"), and just check the type on that:

package main

import (
    "fmt"
    "reflect"
)

type Fish struct {
}

type Cod struct {
    Fish
}

func WhatAmI (self interface{}) string {
    return reflect.TypeOf(self).String()
}

func main() {
    c := new(Cod)
    fmt.Println("I am a", WhatAmI(c))
}

Gives:

I am a *main.Cod
like image 33
Intermernet Avatar answered Nov 07 '22 22:11

Intermernet