如何在Golang中获取子类型

huangapple go评论88阅读模式
英文:

How to get child's type in golang

问题

我最近一直在学习Go语言。在下面的示例中,我得到了类型a,而不是b。为什么会这样呢?我该如何得到b呢?

// 父结构体
type A struct {
	foo string
}

func (a *A) say() {
	// 我想要这里是b,而不是a
	fmt.Println(reflect.ValueOf(a).Type().String())
}

// 子结构体
type B struct {
	A
}

func main() {
	b := new(B)
	b.say()
}
英文:

I've been studying Go recently.
In the under sample, I got the type a, not b. Why?
And how do I get b?

// parent
type A struct {
	foo string
}

func (a *A) say() {
	// I want b here, not a
	fmt.Println(reflect.ValueOf(a).Type().String())
}

// child
type B struct {
	A
}

func main() {
	b := new(B)
	b.say()
}

答案1

得分: 3

你总是得到A的值,因为你只有一个指向A结构体的say()方法。

所以,当你将say()方法应用于B结构体时,编译器会查看B结构体及其字段,以查找B结构体是否有say()方法或者是否有任何具有say()方法的字段。

在你的情况下,B结构体没有任何指向它的方法。但是它有一个包含A结构体的字段,并且该字段有一个say()方法。

所以,每次你在B结构体内调用say()方法时,你都会调用B.A.say(),它会打印出A的值。

否则,如果你想打印出B和A的值,你可以修改你的代码,像下面这个例子一样:

package main
import (
	"fmt"
	"reflect"
)

type A struct {
    foo string
}
// 这个方法将指向A结构体
func (a *A) say() {
    fmt.Println(reflect.ValueOf(a).Type().String())
}

type B struct {
    A
}
// 这个方法将指向B结构体
func (a *B) say() {
    fmt.Println(reflect.ValueOf(a).Type().String())
}

func main() {
    b := new(B)
    b.say()		// 期望输出: *main.B
    b.A.say()	// 期望输出: *main.A
}

输出:

*main.B
*main.A

你也可以在Go Playground上运行这段代码。

英文:

You got always the A value because you have only one say() method which point to A struct.

So, when you apply the say() method to B struct, the compiler will look at B struct and its fileds in order to find if there is a say() method of B struct or there is any field of B struct who have a say() method.

In your case, B struct doesn't have any method which will point to it. But it have a field which cointain A struct and which have a say() method.

So, everytime you'll call the say() method within B struct, you'll call B.A.say() which will print the A value.

Otherwise, if you want to print B and A values, you can modify your code to something like this example:

package main
import (
	"fmt"
	"reflect"
)

type A struct {
    foo string
}
// This method will point to A struct
func (a *A) say() {
    fmt.Println(reflect.ValueOf(a).Type().String())
}

type B struct {
    A
}
// This method will point to B struct
func (a *B) say() {
    fmt.Println(reflect.ValueOf(a).Type().String())
}

func main() {
    b := new(B)
    b.say()		// expected output: *main.B
    b.A.say()	// expected output: *main.A
}

Output:

*main.B
*main.A

You can also run this code with Go Playground

huangapple
  • 本文由 发表于 2016年12月14日 14:17:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/41136004.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定