将项目添加到数组后,我无法修改该项目。

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

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, &amp;newRoom)
   }

   roomManager.allRooms = append(roomManager.allRooms, newRoom)
   return &amp;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(&quot;RoomName&quot;, room.name)
   arwObj.eventParams.PutString(&quot;RoomTag&quot;, room.tag)
   arwObj.eventParams.PutInt(&quot;RoomId&quot;, room.id)
   arwObj.eventParams.PutInt(&quot;RoomCappacity&quot;, room.cappacity)

   usersData := &quot;&quot;
   for ii := 0; ii &lt; len(room.userList); ii++ {
     if room.userList[ii].name != u.name {
       usersData += room.userList[ii].GetDataForOtherUser(u) + &quot;&#39;&#39;&quot;
     }
   }

   usersData = strings.TrimRight(usersData, &quot;&#39;&#39;&quot;)

   arwObj.eventParams.PutString(&quot;Users&quot;, usersData)
   arwServer.SendRequestToUser(u, arwObj)

   var arwObjforTheOthers ARWObject
   arwObjforTheOthers.requestName = User_Enter_Room
   arwObjforTheOthers.eventParams.PutString(&quot;RoomName&quot;, room.name)
   arwObjforTheOthers.eventParams.PutString(&quot;userName&quot;, u.name)
   arwObjforTheOthers.eventParams.PutInt(&quot;userId&quot;, u.id)
   arwObjforTheOthers.eventParams.PutString(&quot;isMe&quot;, &quot;false&quot;)

   room.SendRequestAllUserWithoutMe(*arwServer, arwObjforTheOthers, u)
   fmt.Println(&quot;User join Room - User Name : &quot;, u.name+&quot; Room : &quot;+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 (
	&quot;fmt&quot;
)

type Thing struct {
	Name string
}

func main() {
	things := []Thing{}
	thing := Thing{&quot;thing1&quot;}

	// add to slice
	// note that this is a function call
	things = append(things, thing)

	// attempt to change
	thing.Name = &quot;thing2&quot;
	fmt.Println(things[0].Name) // prints thing1
	fmt.Println(thing.Name)     // prints thing2

	fmt.Println(&quot;------&quot;)
	
	// try again
	thing3 := things[0]
	thing3.Name = &quot;thing3&quot;
	// fail again
	fmt.Println(things[0].Name) // prints thing1
	fmt.Println(thing3.Name)     // prints thing3
	
	fmt.Println(&quot;------&quot;)

	// do this instead
	betterThings := []*Thing{} // slice of pointers
	betterThing := &amp;Thing{&quot;thing2&quot;} // betterThing is of type *Thing

	// add to slice
	betterThings = append(betterThings, betterThing)

	// successfully change
	betterThing.Name = &quot;thing2&quot;

	fmt.Println(betterThings[0].Name) // prints thing2
	fmt.Println(betterThing.Name)     // prints thing2
}

huangapple
  • 本文由 发表于 2017年5月12日 02:21:31
  • 转载请务必保留本文链接:https://go.coder-hub.com/43922965.html
匿名

发表评论

匿名网友

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

确定