-1

I'm trying to learn Golang so I'm writing a "game".

The rooms in the game need to access each other for purposes of sending players to / from rooms. However, I am getting a stack overflow error.

I think I understand why it's happening, but I'm not sure how to resolve it.

I believe it's happening because when I access room1, it tries to initialize room2 which then tries to initilize another room1 which then tries to initilize another room2 forever.

I thought my GetRoom method would save the room's address in memory to an object after it's initialized but it doesn't appear to do what I thought it would.

Any advice would be appreciated.

package main

import "fmt"

type Room struct {
    accesses []*Room
}

type World struct {
    rooms map[string]*Room
}

func (w *World) GetRoom(name string) *Room {
    if room, ok := w.rooms[name]; ok {
        return room
    } else {
        switch name {
        case "room1":
            w.rooms[name] = NewRoom1(w)
        case "room2":
            w.rooms[name] = NewRoom2(w)
        default:
            panic("Room not found")
        }
        return w.rooms[name]
    }
}

func NewRoom1(w *World) *Room {
    return &Room{
        accesses: []*Room{
            w.GetRoom("room2"),
        },
    }
}

func NewRoom2(w *World) *Room {
    return &Room{
        accesses: []*Room{
            w.GetRoom("room1"),
        },
    }
}

func main() {
    world := World{
        rooms: make(map[string]*Room),
    }
    room := world.GetRoom("room1")
    fmt.Println(room)
}
1
  • "I thought my GetRoom method would save the rooms address in memory to an object after its initialized" it would if GetRoom ever returned, but it never gets past the call to NewRoom* which is before the rooms entry gets defined. I'd make accesses a slice of strings and just access the room by name, or initialize an empty Room and populate accesses later. Commented Nov 23, 2024 at 19:00

1 Answer 1

0

One option would be to create a Room before you know all the rooms it is connected to:

func (w *World) GetRoom(name string) *Room {
    if room, ok := w.rooms[name]; ok {
        return room
    } else {
        room := &Room{}
        w.rooms[name] = room
        switch name {
        case "room1":
            room.accesses = NewRoom1(w)
        case "room2":
            room.accesses = NewRoom2(w)
        default:
            panic("Room not found")
        }

        return room
    }
}

then the NewRoom methods will only return the rooms this rooms has access to:

func NewRoom1(w *World) []*Room {
    return []*Room{
        w.GetRoom("room2"),
    }
}

func NewRoom2(w *World) []*Room {
    return []*Room{
        w.GetRoom("room1"),
    }
}

so you can call GetRoom on a partially constructed room and still get a reference.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.