Golang在另一个结构的方法内改变一个结构体的值 [英] Golang changing values of a struct inside a method of another struct

查看:1429
本文介绍了Golang在另一个结构的方法内改变一个结构体的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



这个结构体有一些字段和一个包含切片的字段:

 类型Bot结构{
// ...
connlist []连接
}

这个 Connection 看起来像这样:

 类型连接结构{
conn net.Conn
messages int32
channels [] string
连接int32
connactive bool
}

我的问题是改变数值 connactive true



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

  func(bot * Bot)ListenToConnection (connection connection){
reader:= bufio.NewReader(connection.conn)
tp:= textproto.NewReader(reader)
用于{
行,err:= tp。 ReadLine()
如果err!= nil {
log.Printf(错误读取聊天连接:%s,错误)
break //错误循环break
}
如果strings.Contains(line, tmi.twitch.tv 001){
connection.activateConn()
}
如果strings.Contains(line,PING){
fmt.Fprintf(connection.conn ,PONG tmi.twitch.tv\r\\\

}
fmt.Fprintf(bot.inconn,line +\r\\\

}



$ b $ connection.activeConn()是不正常工作的部分,方法如下所示:

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

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



但是,如果我稍后以 Bot connactive 总是 false 出于某种原因(这是默认值)。

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

我认为我正在处理原始连接的副本,而不是具有 connactive = true 的已更改连接。



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

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



当您调用 ListenToConnection()方法(你没有发布这段代码),你传递一个 Connection 的值。 Go中的所有内容都是按值传递的,因此将复制传入的值。在 ListenToConnection()中,您可以使用此副本进行操作。你可以调用它的 activateConn()方法,但是那个方法(它有一个指针接收器)将接收这个副本的地址(一个局部变量)。



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

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

使用 Bot.connlist 中的值进行调用:

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

循环用 conlist 的每个元素调用它



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

注意!我故意将用于......范围,它只使用索引而不是值。使用一个作为...... range 的索引和值,或者只是该值,你会观察到同样的问题( connactive 将保持 false ):

  for _,v:= range bot.connlist {
bot.ListenToConnection(& v)//不好! v也是副本
}

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


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 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.

这篇关于Golang在另一个结构的方法内改变一个结构体的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆