英文:
I cannot modify the item after appending to array
问题
我正在为Unity引擎开发一个多人游戏API。我有一个Room和RoomManager结构体。当我想创建房间时,我设置房间的名称、ID(所有变量),然后将这个新房间追加到RoomManager结构体的allRoom数组中。之后,当我修改房间变量时,我无法更改任何变量。我不知道为什么?
以下是我的结构体和方法:
RoomManager结构体
type RoomManager struct {
allRooms []Room
roomCounter int
}
Room结构体
type Room struct {
tag string
name string
password string
id int
capacity int
maxVariableCount int
userList []User
roomVariables []RoomVariable
extensionHandlers []ExtensionRequest
InitializeMethod roomInitializeFunc
}
创建房间的方法
func (roomManager *RoomManager) CreateRoom(settings RoomSettings, arwServer *ARWServer) *Room {
var newRoom Room
newRoom.InitializeMethod = settings.InitializeMethod
newRoom.name = settings.name
newRoom.password = settings.password
newRoom.tag = settings.tag
newRoom.capacity = settings.capacity
newRoom.maxVariableCount = settings.maxRoomVariableCount
newRoom.id = roomManager.roomCounter
roomManager.roomCounter++
newRoom.userList = make([]User, 0, newRoom.capacity)
newRoom.roomVariables = make([]RoomVariable, 0, newRoom.maxVariableCount)
if newRoom.InitializeMethod != nil {
newRoom.InitializeMethod(arwServer, &newRoom)
}
roomManager.allRooms = append(roomManager.allRooms, newRoom)
return &newRoom
}
将用户添加到房间的方法
func (room *Room) AddUserToRoom(arwServer *ARWServer, u User) {
room.userList = append(room.userList, u)
var arwObj ARWObject
arwObj.requestName = Join_Room
arwObj.eventParams.PutString("RoomName", room.name)
arwObj.eventParams.PutString("RoomTag", room.tag)
arwObj.eventParams.PutInt("RoomId", room.id)
arwObj.eventParams.PutInt("RoomCapacity", room.capacity)
usersData := ""
for ii := 0; ii < len(room.userList); ii++ {
if room.userList[ii].name != u.name {
usersData += room.userList[ii].GetDataForOtherUser(u) + ","
}
}
usersData = strings.TrimRight(usersData, ",")
arwObj.eventParams.PutString("Users", usersData)
arwServer.SendRequestToUser(u, arwObj)
var arwObjforTheOthers ARWObject
arwObjforTheOthers.requestName = User_Enter_Room
arwObjforTheOthers.eventParams.PutString("RoomName", room.name)
arwObjforTheOthers.eventParams.PutString("userName", u.name)
arwObjforTheOthers.eventParams.PutInt("userId", u.id)
arwObjforTheOthers.eventParams.PutString("isMe", "false")
room.SendRequestAllUserWithoutMe(*arwServer, arwObjforTheOthers, u)
fmt.Println("User join Room - User Name: ", u.name+" Room: "+u.lastRoom.name)
}
请注意,这只是代码的翻译部分,我无法回答关于代码功能的问题。
英文:
I'm developing a multiplayer api for Unity Engine. I have Room and RoomManager struct. When I want create room, I set room name, id (all of variable), after that I append this new room to allRoom array in RoomManager struct. After that when I modified to room variable, I can't change any variable. I dont know why ?
Here is my structs and methods :
RoomManager struct
type RoomManager struct {
allRooms []Room
roomCounter int
}
Room struct
type Room struct {
tag string
name string
password string
id int
cappacity int
maxVariableCount int
userList []User
roomVariables []RoomVariable
extensionHandlers []ExtensionRequest
InitializeMethod roomInitializeFunc
}
Room Create Method
func (roomManager *RoomManager) CreateRoom(settings RoomSettings, arwServer *ARWServer) *Room {
var newRoom Room
newRoom.InitializeMethod = settings.InitializeMethod
newRoom.name = settings.name
newRoom.password = settings.password
newRoom.tag = settings.tag
newRoom.cappacity = settings.cappacity
newRoom.maxVariableCount = settings.maxRoomVariableCount
newRoom.id = roomManager.roomCounter
roomManager.roomCounter++
newRoom.userList = make([]User, 0, newRoom.cappacity)
newRoom.roomVariables = make([]RoomVariable, 0, newRoom.maxVariableCount)
if newRoom.InitializeMethod != nil {
newRoom.InitializeMethod(arwServer, &newRoom)
}
roomManager.allRooms = append(roomManager.allRooms, newRoom)
return &newRoom
}
Add User To Room
func (room *Room) AddUserToRoom(arwServer *ARWServer, u User) {
room.userList = append(room.userList, u)
var arwObj ARWObject
arwObj.requestName = Join_Room
arwObj.eventParams.PutString("RoomName", room.name)
arwObj.eventParams.PutString("RoomTag", room.tag)
arwObj.eventParams.PutInt("RoomId", room.id)
arwObj.eventParams.PutInt("RoomCappacity", room.cappacity)
usersData := ""
for ii := 0; ii < len(room.userList); ii++ {
if room.userList[ii].name != u.name {
usersData += room.userList[ii].GetDataForOtherUser(u) + "''"
}
}
usersData = strings.TrimRight(usersData, "''")
arwObj.eventParams.PutString("Users", usersData)
arwServer.SendRequestToUser(u, arwObj)
var arwObjforTheOthers ARWObject
arwObjforTheOthers.requestName = User_Enter_Room
arwObjforTheOthers.eventParams.PutString("RoomName", room.name)
arwObjforTheOthers.eventParams.PutString("userName", u.name)
arwObjforTheOthers.eventParams.PutInt("userId", u.id)
arwObjforTheOthers.eventParams.PutString("isMe", "false")
room.SendRequestAllUserWithoutMe(*arwServer, arwObjforTheOthers, u)
fmt.Println("User join Room - User Name : ", u.name+" Room : "+u.lastRoom.name)
}
答案1
得分: 3
你的问题是你的结构体中有非指针切片。在所有的结构体中,将切片定义为指针切片,像这样:
Rooms []*Room
你还需要将函数定义为接受指针值,像这样:
func(room *Room) {}
具体来说,Go 是按值传递的。每当你从原始切片中取出某个元素并将其传递给其中一个函数时,它会被复制。使用指针可以修改切片中的实际值。
参考这个示例:https://play.golang.org/p/ZThHrP0pds
package main
import (
"fmt"
)
type Thing struct {
Name string
}
func main() {
things := []Thing{}
thing := Thing{"thing1"}
// 添加到切片
// 注意这是一个函数调用
things = append(things, thing)
// 尝试修改
thing.Name = "thing2"
fmt.Println(things[0].Name) // 输出 thing1
fmt.Println(thing.Name) // 输出 thing2
fmt.Println("------")
// 再试一次
thing3 := things[0]
thing3.Name = "thing3"
// 再次失败
fmt.Println(things[0].Name) // 输出 thing1
fmt.Println(thing3.Name) // 输出 thing3
fmt.Println("------")
// 改为这样
betterThings := []*Thing{} // 指针切片
betterThing := &Thing{"thing2"} // betterThing 的类型是 *Thing
// 添加到切片
betterThings = append(betterThings, betterThing)
// 成功修改
betterThing.Name = "thing2"
fmt.Println(betterThings[0].Name) // 输出 thing2
fmt.Println(betterThing.Name) // 输出 thing2
}
英文:
Your issue is that your structs have non-pointer slices. In all of your structs define your slices as slices of pointers like so
Rooms []*Room
You also need to define your functions to take pointer values, like so
func(room *Room) {}
To elaborate. Go is pass-by-value. Anytime you pull something out of one of your original slices and pass it to one of your functions, it gets a copy. Using pointers modifies the actual value in the slice.
See this example. https://play.golang.org/p/ZThHrP0pds
package main
import (
"fmt"
)
type Thing struct {
Name string
}
func main() {
things := []Thing{}
thing := Thing{"thing1"}
// add to slice
// note that this is a function call
things = append(things, thing)
// attempt to change
thing.Name = "thing2"
fmt.Println(things[0].Name) // prints thing1
fmt.Println(thing.Name) // prints thing2
fmt.Println("------")
// try again
thing3 := things[0]
thing3.Name = "thing3"
// fail again
fmt.Println(things[0].Name) // prints thing1
fmt.Println(thing3.Name) // prints thing3
fmt.Println("------")
// do this instead
betterThings := []*Thing{} // slice of pointers
betterThing := &Thing{"thing2"} // betterThing is of type *Thing
// add to slice
betterThings = append(betterThings, betterThing)
// successfully change
betterThing.Name = "thing2"
fmt.Println(betterThings[0].Name) // prints thing2
fmt.Println(betterThing.Name) // prints thing2
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论