【Golang】go中如何在浏览器上实时显示cmd控制台的输出(流式传输)

灵感来自于:Print the console log to the screen of a webpage continuously using Go Routines

废话不多说,直接上代码(功能:每1秒输出一个数,逐渐递增):

package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"os/exec"

	"github.com/nbari/violetear"
)

func stream(w http.ResponseWriter, r *http.Request) {
	// 使浏览器页面的滚动条始终置于底部
	scroll := `
<body style="word-wrap: break-word; white-space: pre-wrap;"><script>
	// https://stackoverflow.com/questions/14866775/detect-document-height-change
	// Purpose: Make sure the scroll bar is always at the bottom of the page as the page continues to output.
	// create an Observer instance
	const resizeObserver = new ResizeObserver(() =>
		window.scrollTo(0, document.body.scrollHeight)
	)
	// start observing a DOM node
	resizeObserver.observe(document.body)
</script></body>
`
	fmt.Fprint(w, scroll)

	ctx := r.Context()
	ch := make(chan struct{})

	// 每1秒输出一个数,逐渐递增
	cmd := exec.CommandContext(ctx, "python", "-c", "exec(\"import sys\\nimport time\\nfor i in range(100): print(i);sys.stdout.flush();time.sleep(0.1)\")")
	rPipe, wPipe, err := os.Pipe()
	if err != nil {
		log.Fatal(err)
	}
	cmd.Stdout = wPipe
	cmd.Stderr = wPipe
	if err := cmd.Start(); err != nil {
		log.Fatal(err)
	}

	go writeOutput(w, rPipe)

	go func(ch chan struct{}) {
		cmd.Wait()
		wPipe.Close()
		ch <- struct{}{}
	}(ch)

	select {
	case <-ch:
	case <-ctx.Done():
		err := ctx.Err()
		log.Printf("Client disconnected: %s\n", err)
	}
}

func writeOutput(w http.ResponseWriter, input io.ReadCloser) {
	flusher, ok := w.(http.Flusher)
	if !ok {
		http.Error(w, "Streaming not supported", http.StatusInternalServerError)
		return
	}

	// Important to make it work in browsers
	w.Header().Set("Content-Type", "text/event-stream")
	w.Header().Set("Cache-Control", "no-cache")
	w.Header().Set("Connection", "keep-alive")

	in := bufio.NewScanner(input)
	for in.Scan() {
		data := in.Text()
		log.Printf("data: %s\n", data)
		fmt.Fprintf(w, "data: %s\n", data)
		flusher.Flush()
	}
	input.Close()
}

func main() {
	router := violetear.New()
	router.HandleFunc("/", stream, "GET")
	log.Fatal(http.ListenAndServe(":8080", router))
}

编译运行后直接在浏览器上输入http://localhost:8080/就能看到输出结果:
流式传输,实时显示
可以看到在浏览器端实现了cmd的实时显示,流式传输。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值