如何解决Golang中房间互相引用导致的栈溢出错误?
问题分析
你的推测完全正确,栈溢出的根源就是循环初始化递归调用:
- 调用
GetRoom("room1")时,因为map里没有room1,会执行NewRoom1 NewRoom1里调用w.GetRoom("room2"),map里没有room2,执行NewRoom2NewRoom2里又调用w.GetRoom("room1"),此时map里仍然没有room1(因为NewRoom1还没完成返回,没把room1存入map),于是又触发NewRoom1,无限递归直到栈溢出
你期望GetRoom能返回已初始化的房间地址,但问题在于:房间实例还没创建完成、没存入map之前,递归调用GetRoom不会命中缓存。
解决方案:先占位,后填充引用
核心思路是先把空的房间实例存入map,再去设置它的accesses引用,这样递归调用GetRoom时就能直接拿到已存在的实例,避免无限递归。
修改后的代码如下:
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 } // 先创建空房间存入map占位 room := &Room{} w.rooms[name] = room // 根据房间名填充关联房间 switch name { case "room1": room.accesses = []*Room{w.GetRoom("room2")} case "room2": room.accesses = []*Room{w.GetRoom("room1")} default: panic("Room not found") } return room } func main() { world := World{ rooms: make(map[string]*Room), } room := world.GetRoom("room1") fmt.Println("room1地址:", room) fmt.Println("room1关联的room2地址:", room.accesses[0]) fmt.Println("room2关联的room1地址:", room.accesses[0].accesses[0]) }
代码说明
- 第一次调用
GetRoom("room1")时,先创建空Room实例存入map,再去调用w.GetRoom("room2") - 调用
GetRoom("room2")时,同样先创建空实例存入map,然后调用w.GetRoom("room1"),此时map里已经有room1的实例,直接返回,不会再触发新的创建 - 最终两个房间完成互相引用,不会出现无限递归
扩展方案:分离房间定义与初始化
如果后续房间逻辑更复杂,可以把房间的基础创建和关联初始化分开,先批量创建所有房间,再统一设置关联关系,这种方式更清晰,避免递归:
func (w *World) InitRooms() { // 先创建所有房间实例 w.rooms["room1"] = &Room{} w.rooms["room2"] = &Room{} // 再统一设置房间关联 w.rooms["room1"].accesses = []*Room{w.rooms["room2"]} w.rooms["room2"].accesses = []*Room{w.rooms["room1"]} } func main() { world := World{rooms: make(map[string]*Room)} world.InitRooms() room := world.GetRoom("room1") fmt.Println(room) }
内容的提问来源于stack exchange,提问作者Joey Stout
相关产品推荐
相关产品推荐

