How to use Golang's Websocket to develop real-time map functions
In today's web application development, the demand for real-time performance is getting higher and higher, especially when it comes to geographical location. applications, such as real-time map functionality. Golang's Websocket technology can provide fast and real-time two-way communication, which is suitable for the development of real-time map functions. In this article, I will introduce you how to use Golang's Websocket to develop real-time map functions, while providing specific code examples.
1. Basic concepts
1.1 Websocket
Websocket is a new protocol introduced by HTML5. It is a technology that establishes two-way communication on the traditional HTTP protocol. Websocket uses the standard port of HTTP/HTTPS to establish a long connection between the client and the server, so that the server can push data to the client in real time. At the same time, Websocket also supports two-way communication similar to the TCP protocol, allowing the client and server to transmit data at the same time.
1.2 Golang
Golang is a fast, efficient and safe programming language, especially suitable for web development. Golang's Websocket development can use the websocket module provided by the standard net/http library, which is very convenient and simple.
2. Implementation steps
2.1 Environment setup
First, you need to install Golang, which can be downloaded and installed from the official website. Then, enter the following command on the command line to install the websocket module:
go get github.com/gorilla/websocket
2.2 Backend implementation
In Golang, write Websocket The server side is relatively simple. You can use the HandleFunc function of the http library to create a router and specify the request processing function. In the processing function, use the Upgrader function of the websocket library to switch the HTTP protocol to the Websocket protocol, and use the ReadMessage and WriteMessage functions to implement two-way communication. The following is a simple example:
package main import ( "log" "net/http" "github.com/gorilla/websocket" ) func main() { http.HandleFunc("/", serveHome) http.HandleFunc("/ws", handleWebSocket) if err := http.ListenAndServe(":8080", nil); err != nil { log.Fatal("ListenAndServe: ", err) } } func serveHome(w http.ResponseWriter, r *http.Request) { http.ServeFile(w, r, "index.html") } var upgrader = websocket.Upgrader{ ReadBufferSize: 1024, WriteBufferSize: 1024, } func handleWebSocket(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Println(err) return } defer conn.Close() for { messageType, p, err := conn.ReadMessage() if err != nil { log.Println(err) return } log.Printf("Received message: %s", p) err = conn.WriteMessage(messageType, p) if err != nil { log.Println(err) return } } }
2.3 Front-end implementation
In the front-end, use JavaScript to establish a Websocket connection, then use the send function to send information to the server, and use the onmessage function to receive the information pushed by the server. information. The following is a simple example:
var socket = new WebSocket("ws://localhost:8080/ws"); socket.onopen = function(event) { socket.send("Hello, server!"); }; socket.onmessage = function(event) { console.log("Received message: " + event.data); };
3. Real-time map example
Below, we will combine the above two parts and use Golang's Websocket technology to implement a real-time map function.
3.1 Back-end implementation
On the server side, we can use Golang's standard library "net/http" and the third-party library "gorilla/websocket" to implement Websocket communication. The specific code is as follows:
package main import ( "encoding/json" "flag" "fmt" "html/template" "log" "net/http" "sync" "github.com/gorilla/websocket" ) const ( MapWidth = 800 MapHeight = 600 ) var ( port = flag.Int("port", 8888, "http listen port") addr = flag.String("addr", "localhost", "http server address") mu sync.Mutex connections map[*websocket.Conn]bool ) func init() { connections = make(map[*websocket.Conn]bool) } type Position struct { X float64 `json:"x"` Y float64 `json:"y"` } type Location struct { Name string `json:"name"` Position Position `json:"position"` } type Map struct { Name string `json:"name"` ImageURL string `json:"image_url"` Locations []Location `json:"locations"` } var ( maps = []Map{ Map{ Name: "Campus Map", ImageURL: "/static/campus_map.png", Locations: []Location{ Location{ Name: "Library", Position: Position{ X: 400, Y: 300, }, }, Location{ Name: "Dormitory Building", Position: Position{ X: 300, Y: 200, }, }, Location{ Name: "Teaching Building", Position: Position{ X: 500, Y: 400, }, }, }, }, } ) func main() { flag.Parse() http.HandleFunc("/", indexPageHandler) http.HandleFunc("/ws", wsHandler) staticHandler := http.FileServer(http.Dir("static")) http.Handle("/static/", http.StripPrefix("/static/", staticHandler)) addr := fmt.Sprintf("%s:%d", *addr, *port) log.Printf("Starting server on %s", addr) err := http.ListenAndServe(addr, nil) if err != nil { log.Fatal("ListenAndServe: ", err) } } func indexPageHandler(w http.ResponseWriter, r *http.Request) { indexTemplate := template.Must(template.ParseFiles("templates/index.html")) indexTemplate.ExecuteTemplate(w, "index.html", maps) } type Message struct { Action string `json:"action"` Location string `json:"location"` } func wsHandler(w http.ResponseWriter, r *http.Request) { ws, err := websocket.Upgrade(w, r, nil, 1024, 1024) if err != nil { http.Error(w, "Could not open websocket connection", http.StatusBadRequest) return } defer ws.Close() mu.Lock() connections[ws] = true mu.Unlock() for { msgType, msg, err := ws.ReadMessage() if err != nil { delete(connections, ws) return } else { log.Printf("Received: %s ", msg) m := &Message{} if err := json.Unmarshal(msg, m); err != nil { log.Printf("Failed to unmarshal message %s: %v", msg, err) } else { switch m.Action { case "move": sendUpdate(ws, m.Location) updateMap(m.Location) case "logout": delete(connections, ws) } } } for c := range connections { err = c.WriteMessage(msgType, msg) if err != nil { delete(connections, c) log.Printf("Error writing to user [%s]: %v ", c.RemoteAddr(), err) } } } } func updateMap(loc string) { for i := range maps { for j := range maps[i].Locations { if maps[i].Locations[j].Name == loc { maps[i].Locations[j].Position.X += 20 maps[i].Locations[j].Position.Y += 20 } } } } func sendUpdate(ws *websocket.Conn, loc string) { for i := range maps { if maps[i].Name == "Campus Map" { msg := &Message{ Action: "update", Location: loc, } for j := range maps[i].Locations { location := maps[i].Locations[j] msgBody, _ := json.Marshal(location) if err := ws.WriteMessage(websocket.TextMessage, msgBody); err != nil { log.Printf("Could not send message: %v", err) } } break } } }
3.2 Front-end implementation
In the front-end, use JavaScript to establish a Websocket connection, then use the send function to send information to the server, and use the onmessage function to receive messages pushed by the server. . HTML5 live maps can be drawn using SVG tags. The following is a simple example:
<!doctype html> <html> <head> <title>Realtime Map</title> <style> #map { width: 800px; height: 600px; } </style> </head> <body> <svg id="map"> <image xlink:href="{{ .ImageURL }}" width="{{ .Width }}" height="{{ .Height }}" /> {{ range $location := .Locations }} <circle id="{{ $location.Name }}" cx="{{ $location.Position.X }}" cy="{{ $location.Position.Y }}" r="5" fill="red" /> {{ end }} </svg> <script> var ws = new WebSocket("ws://localhost:8888/ws"); ws.onopen = function(event) { console.log("WebSocket connected"); }; ws.onmessage = function(event) { var data = JSON.parse(event.data); if (data.action === "update") { var location = data.location; var $circle = document.getElementById(location.name); var x = parseFloat($circle.getAttribute("cx")); var y = parseFloat($circle.getAttribute("cy")); $circle.setAttribute("cx", x + location.position.x); $circle.setAttribute("cy", y + location.position.y); } }; window.addEventListener("load", function() { var $circles = document.querySelectorAll("#map circle"); for (var i = 0; i < $circles.length; i++) { $circles[i].addEventListener("click", function() { var location = this.id; var msg = { action: "move", location: location }; ws.send(JSON.stringify(msg)); }); } }); </script> </body> </html>
4. Summary
After introducing the basic concepts of Golang's Websocket technology, this article provides a development example of the real-time map function. The above example can draw a map through HTML5 and SVG tags, use Websocket technology to achieve real-time two-way communication, and realize the real-time map function. Of course, the above are just examples. In actual scenarios, appropriate improvements and optimizations need to be made according to specific application requirements.
The above is the detailed content of How to use golang's Websocket to develop real-time map functions. For more information, please follow other related articles on the PHP Chinese website!