### Websocketのハンドリング
connection.go
package domain import "github.com/gorilla/websocket" type WsJsonResponse struct { Action string `json:"action"` Message string `json:"message"` } type WebSocketConnection struct { *websocket.Conn } type WsPlayload struct { Action String `json:"action"` Message string `json:"message"` Username string `json:"username"` Conn WebSocketConnection `json:"-"` }
handlers.go
import ( "chat/domain" "log" "net/http" "fmt" "github.com/CloudyKit/jet/v6" "github.com/gorilla/websocket" ) var views = jet.NewSet( jet.NewOSFileSystemLoader("./html"), jet.InDevelopmentMode(), ) var upgradeConnection = websocket.Upgrader { ReadBufferSize: 1024, WriteBufferSize: 1024, CheckOrigin: func(r *http.Request) bool {return true}, } var ( wsChan = make(chan domain.WsPayload) clients = make(map[domain.WebSocketConnection]string) ) func WsEndpoint(w http.ResponseWriter, r *http.Request){ ws, err := upgradeConnection.Upgrade(w, r, nil) if err != nil { log.Println(err) } log.Println("OK client connecting") conn := domain.WebSocketConnection{Conn: ws} clients[conn] = "" go ListenForWs(&conn) var response domain.WsJsonResponse response.Message = `<li>Connect to server</li>` err = ws.WriteJSON(response) if err != nil { log.Println(err) } } func Home(w http.ResponseWriter, r *http.Request){ err := renderPage(w, "home.jet", nil) if err != nil { log.Println(err) } } func renderPage(w http.ResponseWriter, tmpl string, data jet.VarMap) error { view, err := views.GetTemplate(tmpl) if err != nil { log.Println(err) return err } err = view.Execute(w, data, nil) if err != nil { log.Println(err) return err } return nil } func ListenForWs(conn *domain.WebSocketConnection){ defer func(){ if r := recover(); r != nil { log.Println("Error", fmt.Sprintf("%v", r)) } }() var payload domain.WsPayload for { err := conn.ReadJSON(&payload) if err != nil { } else { payload.Conn = *conn wsChan <- payload } } } func broadcastToAll(response domain.WsJsonResponse){ for client := range clients { err := client.WriteJSON(response) if err != nil { log.Println("websockets err") _ = client.Close() delete(clients, client) } } } func ListenToWsChannel(){ var response domain.WsJsonResponse for { e := <-wsChan response.Action = "Got here" response.Message = fmt.Sprintf("Some message, and action was %s", e.Action) broadcastToAll(response) } }
goroutineを使って、ListenForWs関数を別プロセスで呼び出すことで、ブラウザからの通信を常にキャッチし続ける状態を作る。gorouteは go と書くだけ
main.go
import ( "chat/internal/handlers" "log" "net/http" ) func main(){ mux := routes() log.Println("Starting channel listener") go handlers.ListenToWsChannel() log.Println("Starting web server on port 8080") _ = http.ListenAndServe(":8080", mux) }
successfully connected
script.js:21 {action: ”, message: ‘
‘}
2021/10/18 03:41:26 Error runtime error: invalid memory address or nil pointer dereference
2021/10/18 03:41:30 Error repeated read on failed websocket connection
2021/10/18 03:41:30 OK client connecting
なんか上手くいってるっぽいが、どういう仕組みなのか全然理解できない…