I have an issue with structs and maybe an issue with pointers, if my guess is correct.
This struct has some fields and a field that holds a slice:
type Bot struct {
// ...
connlist []Connection
}
This Connection
looks like this:
type Connection struct {
conn net.Conn
messages int32
channels []string
joins int32
connactive bool
}
My problem is changing the value of connactive
to true
.
Bot
has a method that listens to the connection:
func (bot *Bot) ListenToConnection(connection Connection) {
reader := bufio.NewReader(connection.conn)
tp := textproto.NewReader(reader)
for {
line, err := tp.ReadLine()
if err != nil {
log.Printf("Error reading from chat connection: %s", err)
break // break loop on errors
}
if strings.Contains(line, "tmi.twitch.tv 001") {
connection.activateConn()
}
if strings.Contains(line, "PING ") {
fmt.Fprintf(connection.conn, "PONG tmi.twitch.tv\r\n")
}
fmt.Fprintf(bot.inconn, line+"\r\n")
}
}
And connection.activeConn()
is the part that is not working correctly the method looks like this:
func (connection *Connection) activateConn() {
connection.connactive = true
}
This actually gets executed so it's not an issue of the connection not getting a response or something.
But if I try to loop through it later in a method of Bot
, connactive
is always false
for some reason (which is the default).
for i := 0; i < len(bot.connlist); i++ {
log.Println(bot.connlist[i].connactive)
}
I think I am working with a copy or so of the original connection and not the changed connection that has connactive = true
.
Any ideas? Thanks for the help.
Your
ListenToConnection()
method has one parameter:connection Connection
.When you call this
ListenToConnection()
method (you didn't post this code), you pass a value ofConnection
. Everything in Go is passed by value, so a copy will be made of the passed value. InsideListenToConnection()
you operate with this copy. You call itsactivateConn()
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:Calling it with a value from
Bot.connlist
:A
for
loop calling it with every elements ofconlist
:Attention! I intentionally used a
for ... range
which only uses the index and not the value. Using afor ... range
with index and value, or just the value, you would observe the same issue (connactive
would remainfalse
):Because
v
is also just a copy, passing its address tobot.ListenToConnection()
, that would only point to the copy and not the element in theconnlist
slice.It needs to be slice of pointers to connections. And if this property will be changed concurrently, semaphore is necessary.