2016-04-09 20 views
3

構造体に問題があり、私の推測が正しい場合はポインタに関する問題があります。別の構造体のメソッドの内部で構造体の値を変更するGolang

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

このConnectionは次のようになります:

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

私の問題はtrueconnactiveの値を変更している

この構造体にはいくつかのフィールドやスライスを保持するフィールドがあります。

Bot

が接続をlistenする方法があります。

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を持って変更された接続のコピーまたは元の接続のように働いていないと思います。

アイデア?助けてくれてありがとう。

答えて

4

ListenToConnection()メソッドのパラメータは、connection Connectionです。

このListenToConnection()メソッドを呼び出すと(コードを投稿していない)、Connectionの値を渡します。 Goのすべてが値渡しされるので、渡された値のコピーが作成されます。このコピーではListenToConnection()の内部で作業します。 activateConn()メソッドを呼び出しますが、そのメソッド(ポインタ受信者を持つ)はこのコピーのアドレス(ローカル変数)を受け取ります。値とそれを呼び出す

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

Bot.connlistから:

ソリューションは単純で、ListenToConnection()の変更パラメータがポインタであることを

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

conlistのすべての要素とそれを呼び出すforループ:

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

注意!私は意図的に、値ではなくインデックスのみを使用するfor ... rangeを使用しました。インデックスと値、または単に値を持つfor ... range使用して、あなたが同じ問題を観察するでしょう(connactivefalseを残る):bot.ListenToConnection()にそのアドレスを渡し、また、単にコピーです

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

vので、それだけだろうコピーをポイントし、connlistスライスの要素をポイントしないでください。

+1

ありがとうございます!これは私にポインタをもっと良く理解させました。ループの追加は非常に便利です。 – gempir

+0

bot.ListenToConnection(&bot.connlist [0])---私のためにちょっと醜いようです – Uvelichitel

0

接続のポインタをスライスする必要があります。 このプロパティを同時に変更する場合は、セマフォが必要です。

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 
} 
関連する問題