Fragment Description:

In this example, as the handler() is called, the Response is send through a in-memory Pipe.
Pipe() creates a synchronous in-memory pipe.
It can be used to connect code expecting an io.Reader with code expecting an io.Writer.
Reads on one end are matched with writes on the other, copying data directly between the two; there is no internal buffering.
It is safe to call Read and Write in parallel with each other or with Close.
Close will complete once pending I/O is done.
Parallel calls to Read, and parallel calls to Write, are also safe:
the individual calls will be gated sequentially.


Last update, on 2015, Fri 9 Oct, 16:15:39

/* ... <== see fragment description ... */

package main

import (

var (
    BUF_LEN = 1024

func handler(w http.ResponseWriter, r *http.Request) {
    // the specified command
    cmd := exec.Command("ls")
    // sign: func Pipe() (*PipeReader, *PipeWriter)
    // A PipeReader is the read half of a pipe.
    // A PipeWriter is the write half of a pipe.
    pipeReader, pipeWriter := io.Pipe()
    // the pipe content is streamed to 2 io.Writers
    cmd.Stdout = pipeWriter
    cmd.Stderr = pipeWriter
    go writeCmdOutput(w, pipeReader)
    // Run starts the specified command and waits for it to complete.
    // important to close any opened io.Writer
func writeCmdOutput(res http.ResponseWriter, pipeReader *io.PipeReader) {
    buffer := make([]byte, BUF_LEN)
    for {
        n, err := pipeReader.Read(buffer)
        if err != nil {
        data := buffer[0:n]
        // The Flusher interface is implemented by ResponseWriters
        // that allow an HTTP handler to flush buffered data to the client.
        // Its Flush() sends any buffered data to the client.
        if f, ok := res.(http.Flusher); ok {
        // reset buffer
        for i := 0; i < n; i++ {
            buffer[i] = 0
func main() {
    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)