如何在变量的动态类型上调用方法?

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

How do you invoke a method on the dynamic type of a variable?

问题

我找到了两个问题并阅读了它们:

但是我仍然不明白为什么我尝试映射一个出错的对象:

./aaa.go:21: m.Action undefined (type interface {} is interface with no methods)

type MyStruct struct {
}

func (a *MyStruct) Action() {
	fmt.Println("Hello")
}

func main() {
	var Mstruct map[string]interface{}
	Mstruct = make(map[string]interface{}, 100)
	Mstruct["MyStruct"] = &MyStruct{}
	m := Mstruct["MyStruct"]
	fmt.Println(reflect.TypeOf(m)) // *main.MyStruct
	m.Action()
}

这在动态语言中总是有效的,所以我在静态语言中漏掉了一些东西。

英文:

I found two questions and read them:

But I still don't understand why I tried mapping an Object that got error:

./aaa.go:21: m.Action undefined (type interface {} is interface with no methods)

type MyStruct struct {
}

func (a *MyStruct) Action() {
	fmt.Println("Hello")
}

func main() {
	var Mstruct map[string]interface{}
	Mstruct = make(map[string]interface{}, 100)
	Mstruct["MyStruct"] = &MyStruct{}
	m := Mstruct["MyStruct"]
	fmt.Println(reflect.TypeOf(m)) // *main.MyStruct
	m.Action()
}

This always works in dynamic language, so I miss something in static language.

答案1

得分: 3

表达式

m := Mstruct["MyStruct"]

是一个短变量声明规范说明

如果存在类型,则每个变量都被赋予该类型。否则,每个变量都被赋予赋值语句中相应初始化值的类型。

由于该表达式中没有指定类型,变量m被赋予了相应初始化值Mstruct["MyStruct"]的类型,即interface{}

根据你当前的导入情况,interface{}的方法集是空的。对于类型为interface{}的值,你无法调用任何方法。因此,编译器会拒绝执行

m.Action()

你似乎想要根据变量m的动态类型*MyStruct来使用它作为方法接收者。你可以通过类型断言来实现这一点。例如

dynamic := m.(*MyStruct)
dynamic.Action()

规范说明

如果类型断言成立,则表达式的值是存储在x中的值,其类型是T

这里的类型是*MyStruct,它是你的Action方法的接收者类型。因此,你可以使用变量dynamic来调用该方法。

英文:

The expression

m := Mstruct["MyStruct"]

is a short variable declaration. The specification states

> If a type is present, each variable is given that type. Otherwise,
> each variable is given the type of the corresponding initialization
> value in the assignment.

Since a type is not present in that expression, the variable m is given the type of the corresponding initialization value, Mstruct["MyStruct"]. That type is interface{}.

Based on your current imports, the method set of interface{} is empty. There's nothing you can invoke on a value of ype interface{}. Therefore the compiler rejects

m.Action()

You seem to want to use m as a method receiver based on its dynamic type, *MyStruct. You can do that with a type assertion. For example

dynamic := m.(*MyStruct)
dynamic.Action()

The specification states

> If the type assertion holds, the value of the expression is the value
> stored in x and its type is T.

Its type here is *MyStruct which is the receiver type of your Action method. You can therefore invoke the method with the variable dynamic.

答案2

得分: 2

func main() {
var Mstruct map[string]interface{}
Mstruct = make(map[string]interface{}, 100)
Mstruct["MyStruct"] = &MyStruct{}
m := Mstruct["MyStruct"].(*MyStruct) //这是一个类型断言
fmt.Println(reflect.TypeOf(m)) // *main.MyStruct
m.Action()
}

使用类型断言。在你断言它不是nil并且是指定类型之后,你可以将其视为该类型。

https://golang.org/ref/spec#Type_assertions

https://play.golang.org/p/bJib9g7kDY

英文:
func main() {
    var Mstruct map[string]interface{}
    Mstruct = make(map[string]interface{}, 100)
    Mstruct["MyStruct"] = &MyStruct{}
    m := Mstruct["MyStruct"].(*MyStruct) //This is a type assertion
    fmt.Println(reflect.TypeOf(m)) // *main.MyStruct
    m.Action()
}

Use type assertion. After you assert that it is not nil and of the specified type, you can treat it as that type.

https://golang.org/ref/spec#Type_assertions

https://play.golang.org/p/bJib9g7kDY

huangapple
  • 本文由 发表于 2016年4月6日 09:11:29
  • 转载请务必保留本文链接:https://go.coder-hub.com/36439733.html
匿名

发表评论

匿名网友

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

确定