在Golang中,遍历`interface{}`类型的映射,并对每个项目调用相同的方法。

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

Iterate over map of `interface{}` and call the same method on each item in Golang

问题

我正在开发一个简单的控制台游戏来学习Go语言,但在一个看似简单的问题上遇到了困难。在其他语言中可能没有问题,但在Go语言中似乎几乎不可能。

我在结构体中有一个接口类型的映射作为字段,像这样:

type Room struct {
    // ...
	Components map[string]interface{}
    // ...
}

我需要遍历这个映射,并在映射中存储的每个项上调用Render()方法(假设它们都实现了Render()方法)。例如,在JavaScript或PHP中,这不是问题,但在Go语言中,我整天都在苦苦思索。

我需要像这样的代码:

for _, v := range currentRoom.Components {
	v.Render()
}

但这段代码不起作用,但是当我指定类型并手动调用每个项时,它可以工作:

currentRoom.Components["menu"].(*List.List).Render()
currentRoom.Components["header"].(*Header.Header).Render()

我该如何在映射中的每个项上调用Render()方法?或者如果有更好/不同的方法,请告诉我,因为我已经束手无策了。

英文:

I am working on a simple Console game to learn Go and got stuck on a seemingly simple issue that would be no problem in other languages, but seems almost impossible in Go.

I have a map of interfaces as a field in struct like this:

type Room struct {
    // ...
	Components map[string]interface{}
    // ...
}

And I need to iterate over the map and call a Render() method on each of the items stored in the map (assuming they all implement Render() method. For instance in JS or PHP this would be no problem, but in Go I've been banging my head against the wall the entire day.

I need something like this:

for _, v := range currentRoom.Components {
	v.Render()
}

Which doesn't work, but when I specify the type and call each item individually by hand, it works:

currentRoom.Components["menu"].(*List.List).Render()
currentRoom.Components["header"].(*Header.Header).Render()

How can I call the Render() method on every item in the map? Or if there is some better/different approach to go about it, please enlighten me, because I'm at the end of my rope here.

答案1

得分: 2

定义一个接口:

type Renderable interface {
   Render()
}

然后,只要实现了该方法,你就可以对映射的元素进行类型断言并调用Render方法:

currentRoot.Components["menu"].(Renderable).Render()

要测试某个对象是否可渲染,可以使用:

renderable, ok := currentRoot.Components["menu"].(Renderable)
if ok {
   renderable.Render()
}
英文:

Define an interface:

type Renderable interface {
   Render()
}

Then you can type-assert elements of the map and call Render as long as they implement that method:

currentRoot.Components["menu"].(Renderable).Render()

To test if something is renderable, use:

renderable, ok:=currentRoot.Components["menu"].(Renderable)
if ok {
   renderable.Render()
}

huangapple
  • 本文由 发表于 2023年3月20日 08:33:18
  • 转载请务必保留本文链接:https://go.coder-hub.com/75785779.html
匿名

发表评论

匿名网友

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

确定