5

如何使用匿名字段(或超类)获得正确的结构类型?

我试图让这条鱼将自己描述为鳕鱼:

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())
}

我得到的输出是:

I am a *main.Fish

我想要的是:

I am a *main.Cod
4

2 回答 2

9

得到了正确的答案。你想得到的答案是错误的。

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

f type *main.Fish,它甚至被声明为那个类型 ( f *Fish)。因此它永远不可能是 type *main.Cod

混淆的可能来源: 的方法集Cod继承了其嵌入的匿名字段的方法集,Fish并且没有覆盖它。因此,在“委托”调用WhatAmI的实例上调用,接收者现在是 type 的嵌入字段。CodFish.WhatAmI*main.Fish

覆盖继承方法的示例:

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())
}

操场


输出:

I am a *main.Cod
于 2013-06-04T11:26:51.667 回答
2

对于一个相当通用的解决方案,您可以将WhatAmI函数与Fish类型分开并使用空接口(请参阅Andrew Gerrand 的“反射法则”),然后检查其类型:

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))
}

给出:

I am a *main.Cod
于 2013-06-04T12:19:12.603 回答