使用Golang的channel将时间推送到浏览器

使用Golang的channel将时间推送到浏览器 我正在尝试使用通道将时间推送到浏览器,因此编写了以下代码:

package main

import (
	"net/http"
	"time"
)

type DataPasser struct {
	logs chan string
}

func main() {
	passer := &DataPasser{logs: make(chan string)}
	go func() {
		for {
			passer.logs <- time.Now().String()
		}
	}()

	http.HandleFunc("/", passer.handleHello)
	http.ListenAndServe(":9999", nil)

}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	for {
		w.Write([]byte(<-p.logs))
	}
	/*	for {
			io.WriteString(w, <-p.logs)
		}
	*/
}

它确实工作了,但会不断添加带有新时间的新行,如下所示: enter image description here

我需要的是每次服务器发送时间时,都能得到一行被清除并被新时间替换的文本?有什么帮助吗?

更新

我尝试使用 SSE 服务器发送事件,如下所示,但没有成功:

package main

import (
	"net/http"
	"time"
)

type DataPasser struct {
	logs chan string
}

func main() {
	passer := &DataPasser{logs: make(chan string)}
	t := time.NewTicker(time.Second)
	defer t.Stop()

	go func() {
		for range t.C {
			passer.logs <- time.Now().String()
		}
	}()

	http.HandleFunc("/", passer.handleHello)
	http.ListenAndServe(":9999", nil)

}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	setupCORS(&w, r)
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Internal error", 500)
		return
	}
	for {
		w.Write([]byte(<-p.logs))
		//	c := []byte(<-p.logs)
		//	fmt.Fprint(w, c)
		flusher.Flush()
	}
	/*	for {
			io.WriteString(w, <-p.logs)
		}
	*/
	//  w.Write([]byte("Hi, from Service: " + ws.name))

}

func setupCORS(w *http.ResponseWriter, req *http.Request) {
	(*w).Header().Set("Cache-Control", "no-cache")
	(*w).Header().Set("Access-Control-Allow-Origin", "*")
	(*w).Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE")
	(*w).Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, X-CSRF-Token, Authorization")
}

HTML文件如下:

<html>
<head></head>
<body>
    <div id="counter"  width="500" height="600">
</body>
    <script>
        var source = new EventSource("http://localhost:9999/");
        source.onmessage = function (event) {
            console.log(event)
            var counter = event.data; // JSON.parse(event.data);
            document.getElementById("counter").innerHTML = counter;
        }
    </script>
</html>

更多关于使用Golang的channel将时间推送到浏览器的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

您可以在 onload 方法中使用 XMLHttpRequest 获取服务器发送的数据。

MDN Logo

developer.mozilla.org

MDN Social Share

发送和接收二进制数据 - Web APIs | MDN

可以设置 XMLHttpRequest 对象的 responseType 属性来更改预期的服务器响应类型。可能的值为空字符串(默认值)、“arraybuffer”、“blob”、“document”、“json” 和 “text”。response 属性将…

更多关于使用Golang的channel将时间推送到浏览器的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


要实现每次更新替换同一行文本,需要修改服务器端发送的数据格式和客户端的处理方式。以下是修正后的代码:

服务器端代码:

package main

import (
	"fmt"
	"net/http"
	"time"
)

type DataPasser struct {
	logs chan string
}

func main() {
	passer := &DataPasser{logs: make(chan string)}
	ticker := time.NewTicker(time.Second)
	defer ticker.Stop()

	go func() {
		for range ticker.C {
			passer.logs <- time.Now().Format("2006-01-02 15:04:05")
		}
	}()

	http.HandleFunc("/", passer.handleHello)
	http.ListenAndServe(":9999", nil)
}

func (p *DataPasser) handleHello(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")
	w.Header().Set("Access-Control-Allow-Origin", "*")

	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Streaming unsupported", http.StatusInternalServerError)
		return
	}

	for {
		select {
		case <-r.Context().Done():
			return
		case msg := <-p.logs:
			fmt.Fprintf(w, "data: %s\n\n", msg)
			flusher.Flush()
		}
	}
}

客户端HTML代码:

<!DOCTYPE html>
<html>
<head>
    <title>Time Stream</title>
</head>
<body>
    <div id="time-display" style="font-size: 24px; font-family: monospace;"></div>

    <script>
        const eventSource = new EventSource("http://localhost:9999/");
        
        eventSource.onmessage = function(event) {
            document.getElementById("time-display").textContent = event.data;
        };
        
        eventSource.onerror = function(error) {
            console.error("EventSource failed:", error);
            eventSource.close();
        };
    </script>
</body>
</html>

关键修改点:

  1. SSE格式规范:服务器发送事件必须遵循 data: {message}\n\n 格式,每个事件以双换行符结束
  2. 时间格式化:使用 time.Now().Format("2006-01-02 15:04:05") 获得更易读的时间格式
  3. 上下文处理:添加 r.Context().Done() 检查,确保连接关闭时能正确清理资源
  4. 客户端处理:使用 textContent 而不是 innerHTML 来更新文本内容,这样会替换而不是追加

运行效果:浏览器中会显示一个不断更新的时间文本,每次新时间会替换旧时间,而不是添加新行。

回到顶部