4

I am very new to Go and have found myself working with sockets as my first project. This is a redundant question, but I have failed to understand how to send a websocket update to a specific channel in Go (using Gorilla).

I am using code sample from this link

this method. But failed to modify to send messages to specific channel.

Here is my sample code main.go

func main() {
    flag.Parse()
    hub := newHub()
    go hub.run()
    http.HandleFunc("/ws", func(w http.ResponseWriter, r *http.Request) {
        fmt.Println(hub)
        serveWs(hub, w, r)
    })
    err := http.ListenAndServe(*addr, nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

There is other two files called hub.go and client.go I think hub.go below here something could be done

return &Hub{
    broadcast:  make(chan []byte),
    register:   make(chan *Client),
    unregister: make(chan *Client),
    clients:    make(map[*Client]bool),
}

What should I change from here?

UPDATE

What I am trying to do is I have a socket server written in go. Now suppose we have many clients written in react listening on server with a specific url like wss://abc.com/wss1 or may be wss://abc.com/wss2

Now if client wss1 send a message to server, server will emit this message all clients listening on url wss1 not wss2 and vice versa.

Till now i have been able to do broadcast to all clients irrespective of wss1 or wss2. Hope I made it clear.

4
  • Possible duplicate of Sending a Websocket message to a specific client in Go (using Gorilla) Commented Sep 4, 2019 at 15:23
  • Actually this is not a duplicate. I want to send all client who is listening to a specific channel Commented Sep 5, 2019 at 5:28
  • Describe at a higher-level what you are trying to do. For example, are implementing chat rooms, one to one chat or something else? When you say channel, are you referring to one of the Go channels in the example you linked to or are you referring to chat room or channel as in Slack? Commented Sep 5, 2019 at 11:59
  • @CeriseLimón I have updated my question. please take a look. any help would be appreciated. Commented Sep 5, 2019 at 14:37

1 Answer 1

4

To add a "channel" or "chat room" feature to the Gorilla chat example, do the following. I'll use the word "room" in this answer to avoid confusion with Go channels.

Define a type for messages that includes the payload and a room identifier:

type message struct {
   roomID string
   data []byte
}

Replace the hub broadcast channel with:

broadcast chan message

Add a room identifier to the Client type:

type Client struct {
    roomID string
    hub *Hub
    ...
}

The handler extracts the room identifier from the request URI and sets the room identifier when creating a Client and sending a message.

Change the Hubs clients fields to a map keyed by room identifier. Initialize this field as appropriate when initializing the hub.

// Registered clients by room
rooms map[string]map[*Client]bool

Change the Hub run function to work with rooms. This code is structurally similar to the code in the original example.

    select {
    case client := <-h.register:
        room := h.rooms[client.roomID]
        if room == nil {
           // First client in the room, create a new one
           room = make(map[*Client]bool)
           h.rooms[client.roomID] = room
        }
        room[client] = true
    case client := <-h.unregister:
        room := h.rooms[client.roomID]
        if room != nil {
            if _, ok := room[client]; ok {
                delete(room, client)
                close(client.send)
                if len(room) == 0 {
                   // This was last client in the room, delete the room
                   delete(h.rooms, client.roomID)
                }
            }
         }
    case message := <-h.broadcast:
        room := h.rooms[message.roomID]
        if room != nil {
            for client := range room {
                select {
                case client.send <- message.data:
                default:
                    close(client.send)
                    delete(room, client)
                }
            }
            if len(room) == 0 {
                // The room was emptied while broadcasting to the room.  Delete the room.
                delete(h.rooms, message.roomID)
            }
        }
    }
Sign up to request clarification or add additional context in comments.

4 Comments

Thank you. I will try and let you know.
here i am getting error. room := h.rooms[message.roomID] error is message.roomID undefined (type []byte has no field or method roomID)
Ok. Thanks Man :)
Now hub.go looks fine. but when i try to run getting error from client.go. here is the error "cannot use message (type []byte) as type message in send" on readPump function. Can you please help once more?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.