### 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
なんか上手くいってるっぽいが、どういう仕組みなのか全然理解できない…