GoでWebsocketを使ったリアルタイムチャットを作ってみた

はじめに

勉強がてらGoでWebsocketを使ったチャットアプリを作ってみた時の備忘録です。

作ったもの

github.com

フレームワークとしてはGinを使い、ORMにはgorm v2を使っています。 またWebsocket周りはmelodyを使っています。

github.com

やったこと

細かいところは基本的にはコミットログをにまとまっているのでそちらを見ていただければと思います。

github.com

実装の肝としては、routes/setup.goに以下のようにWebsocket用のルーティングを追加して、

   // チャットルーム用のWebsocket接続先
    router.GET("/rooms/:id/messages/ws", messageController.Websocket)

    m.HandleMessage(func(s *melody.Session, msg []byte) {
        m.Broadcast(msg)
    })

    m.HandleConnect(func(s *melody.Session) {
        log.Printf("websocket connection open. [session: %#v]\n", s)
    })

    m.HandleDisconnect(func(s *melody.Session) {
        log.Printf("websocket connection close. [session: %#v]\n", s)
    })

    // メッセージがブロードキャストされたときの処理
    m.HandleMessage(messageController.Broadcast)

フロント側から接続するときのルーティングとWebsocket周りの接続を設定しています。

あとは、メッセージを作成する処理をコントローラーのアクションを以下のように作成しています。

func (messageController *messageController) Broadcast(s *melody.Session, msg []byte) {

    roomPath := strings.Trim(s.Request.URL.Path, "/roomsmessagews")
    roomID, _ := strconv.ParseUint(roomPath, 10, 64)
    var message model.Message
    message.Content = fmt.Sprintf("%s", msg)
    message.RoomID = roomID
    messageController.messageRepository.Store(messageController.db, &message)

    messageController.m.BroadcastFilter(msg, func(q *melody.Session) bool {
        return q.Request.URL.Path == s.Request.URL.Path
    })
}

あとはフロント側でWebsocketのエンドポイントに接続させておけばいい感じです。

やってみて

意外と簡単に実装できたので今後仕事のコードとかで導入してみてもいいかなと思いました。