英文:
How do you invoke a method on the dynamic type of a variable?
问题
我找到了两个问题并阅读了它们:
- https://stackoverflow.com/questions/36424907/reflection-struct-by-string/36425480#36425480
- https://stackoverflow.com/questions/8103617/call-a-struct-and-its-method-by-name-in-go
但是我仍然不明白为什么我尝试映射一个出错的对象:
./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:
- https://stackoverflow.com/questions/36424907/reflection-struct-by-string/36425480#36425480
- https://stackoverflow.com/questions/8103617/call-a-struct-and-its-method-by-name-in-go
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论