# Go 从os.Stdin读取数据的方式

go语言中,从标准输入(os.Stdin)读取数据的常见方式有下面几种:

# 1. 使用fmt.Scan系列函数

fmt.Scan系列函数提供了简单的从标准输入读取数据的方法。

# 1.1 fmt.Scan

  • 从标准输入读取由空白符(空格、制表符、换行符等)分隔的值,并将这些值保存到提供的参数中。
  • 换行符被视为空白符,因此会忽略掉换行符继续输入。
  • 返回成功扫描的数据个数和遇到的任何错误。如果读取的数据个数比提供的少,会返回一个错误报告原因。
package main

import "fmt"

func main() {
	var a string
	var b int
	fmt.Scan(&a, &b)
	fmt.Println("a:", a)
	fmt.Println("b:", b)
}

// a
// 12
// a: a
// b: 12

# 1.2 fmt.Scanln

  • 类似fmt.Scan,但是它在读取完所有的指定参数后会检查是否有多余的输入。
  • 要求读取的最后一个输入参数必须位于行的末尾,否则会返回一个错误。
  • 换行符被视为结束标识,如果所有参数读取完毕后还有多余的数据(除了换行符),会返回一个错误。
package main

import "fmt"

func main() {
	var in string

	fmt.Scanln(&in)

	fmt.Println("in:", in)

}
// sadasdasda231232
// in: sadasdasda231232

# 1.3 fmt.Scanf

  • 根据格式化字符串从标准输入中读取数据,并将数据存储到提供的参数中。
  • 输入必须和指定的格式的字符串相匹配。否则可能会导致读取失败或者产生意外结果。
  • 换行符如果不影响解析会被忽略,但如果格式化字符串中有换行符,则必须在输入中输入相应的换行符。
package main

import "fmt"

func main() {
	var a string
	var b int
	fmt.Scanf("%s %d", &a, &b)
	fmt.Println("a:", a)
	fmt.Println("b:", b)
}

// a 12
// a: a
// b: 12

# 2. 使用bufio

bufio包提供了更高级的读取方法,可以逐行读取输入,并且可以指定缓冲区大小。

# 2.1 bufio.NewReader

创建一个读取器,可以逐行读取输入。

package main

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

func main() {
	reader := bufio.NewReader(os.Stdin)

	for {
		line, err := reader.ReadString('\n')
		if err != nil {
			fmt.Println("Error reading input:", err)
			break
		}
		fmt.Println("Read line:", line)
	}
}

# 2.2 bufio.Scanner

bufio.Scanner是一个更高级的扫描器,可以逐个读取输入的单词、行等。

package main

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

func main() {
	scanner := bufio.NewScanner(os.Stdin)

	for scanner.Scan() {
		fmt.Println("Read line:", scanner.Text())
	}

	if err := scanner.Err(); err != nil {
		fmt.Println("Error reading input:", err)
	}
}

# 3. 使用io

io包提供了简单的方法来读取整个输入,但这种方法不适合处理大文件。io.ReadAll函数会从提供的io.Reader(在这个例子中是os.Stdin)读取所有数据,直到遇到EOF(文件结束符)。在读取标准输入的情况下,io.ReadAll会一直等待直到程序接收到EOF信号。在Unix系统中,你可以通过按Ctrl+D发送EOF信号;在Windows系统中,可以通过按Ctrl+Z然后回车来发送EOF信号。

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	data, err := io.ReadAll(os.Stdin)
	if err != nil {
		fmt.Println("Error reading input:", err)
		return
	}
	fmt.Println("Read data:", string(data))
	}