2016-09-22 7 views
0

goでの参照の仕組みを理解するのに苦労しています。私は本当にシンプルなメモリ内のパブリッシュ/サブスクライブ機構を書こうと思っています。ここでは、コードです:go-attribute内の参照は変更されません

package sockets 

import (
    "fmt" 

    "github.com/gorilla/websocket" 
) 

type hubSingleton struct { 
    Clients map[string][]*websocket.Conn 
} 

var instance *hubSingleton 

func Hub() *hubSingleton { 

    if instance == nil { 
     fmt.Println("New instance created") 
     instance = &hubSingleton{} 
    } 
    instance.Clients = make(map[string][]*websocket.Conn, 6) 
    return instance 
} 

func (hub *hubSingleton) Subscribe(channel string, socket *websocket.Conn) error { 
    if _, ok := hub.Clients[channel]; !ok { 
     hub.Clients[channel] = make([]*websocket.Conn, 0) 
    } 
    hub.Clients[channel] = append(hub.Clients[channel], socket) 

    fmt.Println("Subscribe: ", hub.Clients) 
    return nil 
} 

func (hub *hubSingleton) Publish(channel string, message interface{}) { 
    fmt.Println("Publish: ", hub.Clients) 

    if _, ok := hub.Clients[channel]; !ok { 
     return 
    } 
    for i := 0; i < len(hub.Clients[channel]); i++ { 
     conn := hub.Clients[channel][i] 
     conn.WriteJSON(Message{status: "ok", content: message}) 
    } 
} 

問題は、すべての時間が私はハブを呼んでいるようだということです()()またはハブ()を発行し、新しいhubSingleton.Clientが作成されます)(購読します。。。まあ、私は何が起こるかわからないんだけど、ここで実行中のプログラムの出力があります:

Publish: map[] 
Subscribe: map[chan:[0xc820170000]] 
Publish: map[] 
Subscribe: map[chan:[0xc82008ac80]] 
Publish: map[] 
Publish: map[] 
Publish: map[] 
Subscribe: map[chan:[0xc820170140]] 
Publish: map[] 

加入者は、()私はハブを呼び出す地図disapearに毎回追加しました。 地図の変更を通話間で維持できるようにするにはどうすればよいですか?

+0

このコードをどのように呼び出すのかについては、投稿コードを投稿してください。 – eduncan911

答えて

2

関数は、すべての呼び出しで新しいクライアントマップを作成します。 Hubへの最初の呼び出しは、要求ハンドラから、その後、instance上のデータ競合があるとされている場合は

func Hub() *hubSingleton { 
    if instance == nil { 
    fmt.Println("New instance created") 
    instance = &hubSingleton{} 
    instance.Clients = make(map[string][]*websocket.Conn, 6) 
    } 
    return instance 
} 

:に関数を変更します。レースを修正するためにロックを使用します。

var (
    instance *hubSingleton 
    mu sync.Mutex 
) 

func Hub() *hubSingleton { 
    mu.Lock() 
    defer mu.Unlock() 
    if instance == nil { 
    fmt.Println("New instance created") 
    instance = &hubSingleton{} 
    instance.Clients = make(map[string][]*websocket.Conn, 6) 
    } 
    return instance 
} 

単純なアプローチは、使用前に一度インスタンスを初期化することである。

var instance *hubSingleton 

func newHub() *hubSingleton { 
    return &hubSingleton{Clients: make(map[string][]*websocket.Conn, 6)} 
} 

func main() { 
    instance = newHub() 
    ... 
} 

PublishSubscribeがハンドラによって同時に呼び出されている場合は、上のデータ競合がありますClientsPublishおよびSubscribeとする。

関連する問題