Golang 在另一个结构的方法中更改一个结构的值
Golang changing values of a struct inside a method of another struct
如果我的猜测是正确的话,我的结构有问题,指针也可能有问题。
这个结构有一些字段和一个包含切片的字段:
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
.
的已更改连接
有什么想法吗?感谢您的帮助。
您的 ListenToConnection()
方法有一个参数:connection Connection
.
当您调用此 ListenToConnection()
方法时(您没有 post 此代码),您传递了一个值 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
切片中的元素。
它需要是连接指针的切片。
而如果这个属性会被并发改变,那么semaphore是必须的。
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
}
如果我的猜测是正确的话,我的结构有问题,指针也可能有问题。
这个结构有一些字段和一个包含切片的字段:
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
.
有什么想法吗?感谢您的帮助。
您的 ListenToConnection()
方法有一个参数:connection Connection
.
当您调用此 ListenToConnection()
方法时(您没有 post 此代码),您传递了一个值 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
切片中的元素。
它需要是连接指针的切片。 而如果这个属性会被并发改变,那么semaphore是必须的。
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
}