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