Golang changing values of a struct inside a method of another struct

送分小仙女□ 提交于 2019-12-04 13:22:22

Your ListenToConnection() method has one parameter: connection Connection.

When you call this ListenToConnection() method (you didn't post this code), you pass a value of Connection. Everything in Go is passed by value, so a copy will be made of the passed value. Inside ListenToConnection() you operate with this copy. You call its activateConn() method, but that method (which has a pointer receiver) will receive the address of this copy (a local variable).

Solution is simple, change parameter of ListenToConnection() to be a pointer:

func (bot *Bot) ListenToConnection(connection *Connection) {
    // ...
}

Calling it with a value from Bot.connlist:

bot.ListenToConnection(&bot.connlist[0])

A for loop calling it with every elements of conlist:

for i := range bot.connlist {
    bot.ListenToConnection(&bot.conlist[i])
}

Attention! I intentionally used a for ... range which only uses the index and not the value. Using a for ... range with index and value, or just the value, you would observe the same issue (connactive would remain false):

for _, v := range bot.connlist {
    bot.ListenToConnection(&v) // BAD! v is also a copy
}

Because v is also just a copy, passing its address to bot.ListenToConnection(), that would only point to the copy and not the element in the connlist slice.

It needs to be slice of pointers to connections. And if this property will be changed concurrently, semaphore is necessary.

type Bot struct {
    // ...
    conns []*Connection
}

func (bot *Bot) ListenToConnection(c *Connection) {
   // code
}

type Connection struct {
    conn         net.Conn
    messages     int32
    channels     []string
    joins        int32
    isActive     bool
    isActiveLock sync.RWMutex
}

func (c *Connection) activateConn() {
    c.isActiveLock.Lock()
    defer c.isActiveLock.Unlock()

    c.isActive = true
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!