一尘不染

Golang在另一个结构的方法内部更改一个结构的值

go

如果我的猜测正确的话,我可能会遇到结构问题,可能还会遇到指针问题。

该结构具有一些字段和一个包含切片的字段:

type Bot struct {
    // ...
    connlist []Connection
}

Connection看起来是这样的:

type Connection struct {
    conn       net.Conn
    messages   int32
    channels   []string
    joins      int32
    connactive bool
}

我的问题是将的值更改connactivetrue

Bot 有一个监听连接的方法:

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")
    }
}

并且connection.activeConn()是无法正常工作的部分,该方法如下所示:

func (connection *Connection) activateConn() {
    connection.connactive = true
}

这实际上被执行了,所以连接没有得到响应或其他问题不是问题。

但是,如果以后尝试使用的方法来遍历它Botconnactive则总是false出于某种原因(默认设置)。

for i := 0; i < len(bot.connlist); i++ {
        log.Println(bot.connlist[i].connactive)
}

我想我正在使用的是原始连接的副本,而不是原始的连接connactive = true

有任何想法吗?谢谢您的帮助。


阅读 196

收藏
2020-07-02

共1个答案

一尘不染

您的ListenToConnection()方法有一个参数:connection Connection

调用此ListenToConnection()方法时(未发布此代码),您传递了值Connection。Go中的所有内容都是按值传递的,因此将复制所传递的值。在内部ListenToConnection()使用此副本进行操作。您调用其activateConn()方法,但是该方法(具有指针接收器)将接收此副本的地址(局部变量)。

解决方法很简单,将参数更改ListenToConnection()为指针:

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

用的值调用它Bot.connlist

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

for环带的每一个元素调用它conlist

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

注意! 我故意使用for ... range仅使用索引而不使用值的a。使用for ... range带索引和值(或仅带值)的with,您将观察到相同的问题(connactive将仍然存在false):

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

因为v它也是一个副本,将其地址传递给bot.ListenToConnection(),所以它只会指向副本,而不是connlist切片中的元素。

2020-07-02