Go: How do I remove an element from a slice and modify it in memory
我正在尝试编写一个简单的服务器/客户端聊天程序以用于学习目的,但我遇到了麻烦。 我想让
示例:输入,输出
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | type Room struct { Name string Visitors []*net.Conn } func (r *Room) Leave(pc *net.Conn) { for i, pv := range r.Visitors { //found the connection we want to remove if pc == pv { fmt.Printf("Before %v ",r.Visitors) r.Visitors = append(r.Visitors[:i], r.Visitors[i+1:]...) fmt.Printf("Before %v ",r.Visitors) return } } } |
删除逻辑是正确的(您的输出也确认了这一点)。问题是多个goroutine之间缺乏同步(您的问题对此一无所知)。
您说(在您的评论中)您希望它首先使用1个goroutine,然后再处理同步。但是您的代码已经使用了多个goroutine,因此您将无法获得如此奢侈的体验:
1 2 | //Let a goroutine Handle the connection go handleConnection(conn) |
多个goroutine正在读写
一个示例是使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | type Room struct { Name string Visitors []net.Conn mux sync.RWLock } func (r *Room) Leave(c net.Conn) { r.mux.Lock() defer r.mux.Unlock() for i, v := range r.Visitors { //found the connection we want to remove if c == v { fmt.Printf("Before remove %v ", r.Visitors) r.Visitors = append(r.Visitors[:i], r.Visitors[i+1:]...) fmt.Printf("After remove %v ", r.Visitors) return } } } |
同样,每当其他任何代码触摸
同样,您需要同步访问由多个goroutine读取/更改的所有变量。
还应考虑将移除后释放的元素清零,否则基础数组仍将保留该值,从而阻止gargabe收集器正确释放其使用的内存。有关此的更多信息,请参阅去垃圾收集部分切片吗?
您正在使用
您应该只使用声明
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | type Room struct { Name string Visitors []net.Conn // should not be a pointer to interface value } func (r *Room) Leave(pc net.Conn) { // same thing as above for i, pv := range r.Visitors { // found the connection we want to remove // in the comparison below actual concrete types are being compared. // both these concrete types must be comparable (they can't be slices for example if pc == pv { r.Visitors = append(r.Visitors[:i], r.Visitors[i+1:]...) return } } } |
请注意,上面的比较(
另外,请参考以下问题:为什么不能将* Struct分配给* Interface?