【问题标题】:Golang changing values of a struct inside a method of another structGolang 在另一个结构的方法中更改结构的值
【发布时间】:2016-07-30 18:23:30
【问题描述】:

如果我的猜测是正确的,我的结构和指针可能有问题。

这个结构有一些字段和一个保存切片的字段:

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

这个Connection 看起来像这样:

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

我的问题是将connactive 的值更改为true

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
}

这实际上是被执行的,所以这不是连接没有得到响应之类的问题。

但是如果我稍后尝试在 Bot 的方法中循环遍历它,由于某种原因(这是默认值),connactive 始终是 false

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

我认为我正在使用原始连接的副本左右,而不是具有connactive = true 的更改连接。

有什么想法吗?感谢您的帮助。

【问题讨论】:

    标签: pointers go struct slice


    【解决方案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,它只使用索引而不是值。使用带有索引和值的for ... range 或仅使用值,您会观察到相同的问题(connactive 将保持为false):

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

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

    【讨论】:

    • 谢谢!这让我更好地理解了指针。并且循环添加非常有用。
    • bot.ListenToConnection(&bot.connlist[0]) ---对我来说有点难看
    【解决方案2】:

    它需要是指向连接的指针切片。 如果这个属性会同时改变,信号量是必要的。

    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
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2021-09-25
      • 1970-01-01
      相关资源
      最近更新 更多