Rumah > pembangunan bahagian belakang > Golang > Bagaimana untuk Menstrim Respons dalam Golang dan Mengatasi Had Penimbalan `http.ResponseWriter`?

Bagaimana untuk Menstrim Respons dalam Golang dan Mengatasi Had Penimbalan `http.ResponseWriter`?

Patricia Arquette
Lepaskan: 2024-12-20 06:40:18
asal
289 orang telah melayarinya

How to Stream Responses in Golang and Overcome `http.ResponseWriter` Buffering Limitations?

Menstrim Respons dalam Golang: Halangan Penimbal ResponseWriter

Apabila mencipta aplikasi web di Golang, adalah penting untuk memahami gelagat http. ResponseWriter. Secara lalai, Respons ditimbal, yang bermaksud data dikumpul dan dihantar dalam blok sebaik sahaja permintaan diproses sepenuhnya. Walau bagaimanapun, dalam senario di mana anda ingin menstrim respons kepada pelanggan baris demi baris atau mengendalikan output besar yang melebihi kapasiti penimbalan, tingkah laku ini menjadi penghalang.

Pertimbangkan contoh berikut:

func handle(res http.ResponseWriter, req *http.Request) {
  fmt.Fprintf(res, "sending first line of data")
  sleep(10) // Simulation of a long-running process
  fmt.Fprintf(res, "sending second line of data")
}
Salin selepas log masuk

Dari perspektif pelanggan, mesej "menghantar baris pertama data" dan "menghantar baris data kedua" harus diterima secara berasingan. Walau bagaimanapun, disebabkan penimbalan, kedua-dua baris akan diagregatkan dan dihantar serentak.

Untuk menyelesaikan isu ini, seseorang boleh mengepam ResponseWriter secara manual selepas setiap operasi tulis. Ini boleh dicapai menggunakan antara muka Flusher, seperti yang ditunjukkan di bawah:

func handle(res http.ResponseWriter, req *http.Request) {
  fmt.Fprintf(res, "sending first line of data")
  if f, ok := res.(http.Flusher); ok {
    f.Flush()
  }
  sleep(10) // Simulation of a long-running process
  fmt.Fprintf(res, "sending second line of data")
}
Salin selepas log masuk

Dengan pengubahsuaian ini, respons akan distrim secara progresif kepada klien, seperti yang dikehendaki.

Senario Lanjutan : Perintah Luaran Paip

Walau bagaimanapun, dalam situasi tertentu, curahan manual mungkin tidak mencukupi. Pertimbangkan senario di mana anda ingin menyalurkan output arahan luaran kepada pelanggan. Perintah menjana sejumlah besar data, melebihi kapasiti penimbalan.

pipeReader, pipeWriter := io.Pipe()
cmd.Stdout = pipeWriter
cmd.Stderr = pipeWriter
go writeCmdOutput(res, pipeReader)
err := cmd.Run()
pipeWriter.Close()

// Function to write command output to ResponseWriter
func writeCmdOutput(res http.ResponseWriter, pipeReader *io.PipeReader) {
  buffer := make([]byte, BUF_LEN)
  for {
    n, err := pipeReader.Read(buffer)
    if err != nil {
      pipeReader.Close()
      break
    }

    data := buffer[0:n]
    res.Write(data)
    if f, ok := res.(http.Flusher); ok {
      f.Flush()
    }
    // Reset buffer
    for i := 0; i < n; i++ {
      buffer[i] = 0
    }
  }
}
Salin selepas log masuk

Dalam kes ini, adalah perlu untuk "autoflush" ResponseWriter untuk memastikan data distrim kepada klien tanpa berlengah-lengah. Ini boleh dicapai menggunakan coretan kod yang disediakan.

Penyelesaian Alternatif

Sebagai alternatif kepada terus memaipkan output arahan luaran, seseorang boleh menggunakan pendekatan berasaskan saluran:

// Create a channel to communicate with the goroutine
outputChan := make(chan string)

// Start a goroutine to process the command output
go func() {
  scanner := bufio.NewScanner(cmd.Stdout)
  for scanner.Scan() {
    outputChan <- scanner.Text()
  }
  if err := scanner.Err(); err != nil {
    log.Fatal(err)
  }
  close(outputChan) // Notify that all output has been processed
}()

// Stream output to ResponseWriter lazily
func handleCmdOutput(res http.ResponseWriter, req *http.Request) {
  if f, ok := res.(http.Flusher); ok {
    for {
      select {
      case output := <-outputChan:
        res.Write([]byte(output + "\n"))
        f.Flush()
      default:
        time.Sleep(10 * time.Millisecond)
      }
    }
  }
}
Salin selepas log masuk

Dalam pendekatan ini, goroutine memproses output arahan secara tidak segerak dan menghantarnya ke saluran. Fungsi handleCmdOutput kemudian secara malas menstrim output ke ResponseWriter, mengepam selepas setiap operasi tulis.

Dengan memanfaatkan antara muka Flusher dan meneroka pendekatan alternatif, anda boleh menstrim data dengan berkesan kepada pelanggan dan mengatasi had penimbalan dalam ResponseWriter Golang.

Atas ialah kandungan terperinci Bagaimana untuk Menstrim Respons dalam Golang dan Mengatasi Had Penimbalan `http.ResponseWriter`?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan