2

I have a large buffer (buffer []byte) that I would like to print to stdout but pipe through a pager like less or more. Kind of like the man command. I don't want to write the buffer to tmp file first or make the user manually pipe the output to a pager on the command line.

I can find examples of how to pipe the output of one command to another, but nothing starting with an internal buffer.

Any ideas? Thanks.

Community
  • 1
  • 1
grymoire
  • 27
  • 5

2 Answers2

2

In order to pipe to a pager, you can do something like this:

package main

import (
        "fmt"
        "io"
        "os"
        "os/exec"
)

func main() {
        // declare your pager
        cmd := exec.Command("less")
        // create a pipe (blocking)
        r, stdin := io.Pipe()
        // Set your i/o's
        cmd.Stdin = r
        cmd.Stdout = os.Stdout
        cmd.Stderr = os.Stderr

        // Create a blocking chan, Run the pager and unblock once it is finished
        c := make(chan struct{})
        go func() {
                defer close(c)
                cmd.Run()
        }()

        // Pass anything to your pipe
        fmt.Fprintf(stdin, "hello world\n")

        // Close stdin (result in pager to exit)
        stdin.Close()

        // Wait for the pager to be finished
        <-c
}
creack
  • 116,210
  • 12
  • 97
  • 73
  • 1
    Just wondering why you didn't use `cmd.Start()` and `cmd.Wait()` which gets rid of the need for the blocking chan? – Nick Craig-Wood Feb 12 '14 at 21:36
  • Because you can have only one cmd.Wait() where you can have N `<-c`. So if you need to wait for it on different places, it is better not to rely on Wait. – creack Feb 13 '14 at 20:16
0

Sounds like what you need is an Encoder. Are you using a package for the pager? If so you might want to look for an Encoder in the package, or create your own if one isn't provided.

Here is an example of how you could use a JSON Encoder to achieve something similar to what you're trying to do:

b := []byte(`{ ... some json object ... }`)
json_encoder := json.NewEncoder(os.Stdout)
json_encoder.Encode(b)

In this example, the JSON encoder accepts the []byte and does all the work to encode it into a JSON document and write to the provided io.writer. If you're using a package and it doesn't provide an encoder, you can get ideas on how to write one by looking into the JSON Encoder source code to create your own.

Verran
  • 3,942
  • 2
  • 14
  • 22