go中的引用-属性不变

I'm having hard time understanding how references in go work. I want to write a really simple in-memory publish-subscribe mechanism. Here's the code:

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})
    }
}

The problem is that it seems that every time I call Hub().Publish() or Hub().Subscribe() a new hubSingleton.Client is created. Well, I'm not sure what happens, but here's the output of running program:

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

Subscribers added to the map disapear every time I call Hub(). What can I do, to make the changes in map be preserved between calls?

The Hub function creates a new client map on every call. Change the function to:

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

If the first call to Hub is from a request handler, then there's a data race on instance. Use a lock to fix the race:

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
}

A simpler approach is to initialize the instance once before use:

var instance *hubSingleton

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

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

If Publish and Subscribe are called concurrently by handlers, then there are data races on Clients in Publish and Subscribe.