# 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))
}