在golang中读取stdin的输入

时间:2017-08-28 07:39:56

标签: go stdin

我有这个代码:

func readTwoLines() {
    reader := bufio.NewReader(os.Stdin)
    line, _ := reader.ReadString('\n')
    fmt.Println(line)
    line, _ = reader.ReadString('\n')
    fmt.Println(line)
}

输入:

hello
bye

输出是:

hello
bye

一切都好。但现在,如果我每行创建一个阅读器:

func readTwoLines() {
  line, _ := bufio.NewReader(os.Stdin).ReadString('\n')
  fmt.Println(line)
  line, err := bufio.NewReader(os.Stdin).ReadString('\n')
  if err != nil {
    fmt.Println(err)
  }    
  fmt.Println(line)
}

在第二行读取时出现EOF错误。

为什么会这样?

1 个答案:

答案 0 :(得分:6)

对于简单使用,Scanner可能更方便 你不应该使用两个读者,首先读取缓冲区4096字节的输入

// NewReader returns a new Reader whose buffer has the default size.
func NewReader(rd io.Reader) *Reader {
  return NewReaderSize(rd, defaultBufSize)
}

defaultBufSize = 4096

甚至你的输入包含4000个字节,仍然是第二个读取没有任何东西可读。 但如果输入的输入超过4096个字节,它将起作用。

  

如果ReadString在找到分隔符之前遇到错误,那么   返回错误之前读取的数据和错误本身(通常   io.EOF)。

它是设计的,请参阅doc:

// ReadString reads until the first occurrence of delim in the input,
// returning a string containing the data up to and including the delimiter.
// If ReadString encounters an error before finding a delimiter,
// it returns the data read before the error and the error itself (often io.EOF).
// ReadString returns err != nil if and only if the returned data does not end in
// delim.
// For simple uses, a Scanner may be more convenient.
func (b *Reader) ReadString(delim byte) (string, error) {
    bytes, err := b.ReadBytes(delim)
    return string(bytes), err
}

试试这个:

package main

import (
    "bufio"
    "fmt"
    "os"
)

func main() {
    scanner := bufio.NewScanner(os.Stdin)
    for scanner.Scan() {
        fmt.Println(scanner.Text()) // Println will add back the final '\n'
    }
    if err := scanner.Err(); err != nil {
        fmt.Fprintln(os.Stderr, "reading standard input:", err)
    }
}

运行:

go run m.go < in.txt

输出:

hello
bye

in.txt档案:

hello
bye

我希望这会有所帮助。