Go的分页输出

时间:2015-02-24 20:33:45

标签: go stdout pager

我正在尝试使用$PAGER从golang打印到stdout,或者手动调用moreless以允许用户轻松滚动浏览很多选项。我怎样才能做到这一点?

4 个答案:

答案 0 :(得分:2)

您可以使用os/exec包启动运行less(或$PAGER中的任何内容)的进程,然后将字符串传递给其标准输入。以下对我有用:

func main() {
    // Could read $PAGER rather than hardcoding the path.
    cmd := exec.Command("/usr/bin/less")

    // Feed it with the string you want to display.
    cmd.Stdin = strings.NewReader("The text you want to show.")

    // This is crucial - otherwise it will write to a null device.
    cmd.Stdout = os.Stdout

    // Fork off a process and wait for it to terminate.
    err := cmd.Run()
    if err != nil {
        log.Fatal(err)
    }
}

答案 1 :(得分:2)

我假设您已经从您的程序打印到stdout的输出,您想要捕获并发送到您的寻呼机,您不希望 重写I / O以使用其他响应所需的其他输入流。

您可以创建一个os.Pipe,其工作方式与运行带有“| less”的命令相同,方法是将一侧连接到寻呼机,另一侧连接到stdout,如下所示:

// Create a pipe for a pager to use
r, w, err := os.Pipe()
if err != nil {
    panic("You probably want to fail more gracefully than this")
}

// Capture STDOUT for the Pager. Keep the old
// value so we can restore it later.
stdout := os.Stdout
os.Stdout = w

// Create the pager process to execute and attach
// the appropriate I/O streams.
pager := exec.Command("less")
pager.Stdin = r
pager.Stdout = stdout // the pager uses the original stdout, not the pipe
pager.Stderr = os.Stderr

// Defer a function that closes the pipe and invokes
// the pager, then restores os.Stdout after this function
// returns and we've finished capturing output.
//
// Note that it's very important that the pipe is closed,
// so that EOF is sent to the pager, otherwise weird things 
// will happen.
defer func() {
    // Close the pipe
    w.Close()
    // Run the pager
    if err := pager.Run(); err != nil {
        fmt.Fprintln(os.Stderr, err)
    }
    // restore stdout
    os.Stdout = stdout
}()

答案 2 :(得分:1)

这是一个有点天真的 cat 示例,在设置时会使用$PAGER

package main

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

func main() {
        var out io.WriteCloser
        var cmd *exec.Cmd

        if len(os.Args) != 2 {
                log.Fatal("Wrong number of args: gcat <file>")
        }
        fileName := os.Args[1]
        file, err := os.Open(fileName)
        if err != nil {
                log.Fatal("Error opening file: ", err)
        }

        pager := os.Getenv("PAGER")

        if pager != "" {
                cmd = exec.Command(pager)

                var err error
                out, err = cmd.StdinPipe()
                if err != nil {
                        log.Fatal(err)
                }

                cmd.Stdout = os.Stdout

                if err := cmd.Start(); err != nil {
                        log.Fatal("Unable to start $PAGER: ", err)
                }

        } else {
                out = os.Stdout
        }

        _, err = io.Copy(out, file)
        if err != nil {
                log.Fatal(err)
        }

        file.Close()
        out.Close()

        if cmd != nil {
                if err := cmd.Wait(); err != nil {
                        log.Fatal("Error waiting for cmd: ", err)
                }
        }

}

答案 3 :(得分:0)

此版本为您要分页的所有输出创建一个名为io.Writer的{​​{1}}(如果愿意,可以将其分配给pager),并正确关闭它并等待{ os.Stdout返回时为{1}}。

$PAGER