使用Golang从stdin读取长文本的最佳实践
使用Golang从stdin读取长文本的最佳实践 我想使用 Golang 的 stdin 模块输入并读取超过 10000 个字符的字符串。
然而,根据我目前对 Golang 的了解,我只能读取前 4096 个字符。
因此,我希望有人能帮助我解决这个问题。
谢谢。
- 如果需要逐行处理输入,使用
bufio.Reader更为合适。 - 如果需要将整个输入读取为单个字符串,且不关心内存使用情况,
io.ReadAll则更简单。
更多关于使用Golang从stdin读取长文本的最佳实践的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
你当前的方法是什么?实际上,从标准输入读取数据应该没有大小限制。
使用 os.ReadAll 来读取 os.Stdin 应该是可行的。
package main
import (
"io"
"os"
)
func main() {
res, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
println(len(res))
}
它将标准输入读取到一个缓冲区,并将其追加到结果缓冲区,直到发生错误。如果错误是 io.EOF,则返回收集到的缓冲区。否则,返回该错误。它的工作方式有点像下面的代码片段。
package main
import (
"io"
"os"
)
func main() {
buf := make([]byte, 1024)
var res []byte
for {
n, err := os.Stdin.Read(buf)
res = append(res, buf[:n]...)
if err == io.EOF {
break
}
if err != nil {
panic(err)
}
}
println(len(res))
}
希望这能有所帮助。
你好,@zekro 首先,感谢你的回复。
我正在尝试完成这个 Hackerrank 任务:Goodland Electricity
但对于这个测试用例,我需要先从标准输入读取 100000 个字符。
所以如果可能的话,我希望你能帮我修复这个测试用例的问题。
谢谢。
我想使用 Golang 的 stdin 模块输入并读取一个超过 10000 个字符的字符串。
然而,以我目前对 Golang 的了解,我只能读取前 4096 个字符。
所以我希望有人能帮我解决这个问题。
谢谢。
在Go中从stdin读取长文本时,常见的bufio.Scanner默认缓冲区大小为4096字节,这解释了您遇到的情况。以下是几种处理长文本输入的方法:
方法1:增大Scanner的缓冲区大小
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// 增大缓冲区大小到64KB(可根据需要调整)
buf := make([]byte, 0, 64*1024)
scanner.Buffer(buf, 1024*1024) // 最大容量设为1MB
var input string
for scanner.Scan() {
input += scanner.Text() + "\n"
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "读取错误: %v\n", err)
return
}
fmt.Printf("读取字符数: %d\n", len(input))
}
方法2:使用io.ReadAll(Go 1.16+)
package main
import (
"fmt"
"io"
"os"
)
func main() {
// 一次性读取所有输入
data, err := io.ReadAll(os.Stdin)
if err != nil {
fmt.Fprintf(os.Stderr, "读取错误: %v\n", err)
return
}
input := string(data)
fmt.Printf("读取字符数: %d\n", len(input))
fmt.Printf("前100个字符: %s\n", input[:min(100, len(input))])
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
方法3:使用bufio.Reader分块读取
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
reader := bufio.NewReader(os.Stdin)
var input []byte
buf := make([]byte, 4096) // 每次读取4KB
for {
n, err := reader.Read(buf)
if n > 0 {
input = append(input, buf[:n]...)
}
if err != nil {
if err.Error() == "EOF" {
break
}
fmt.Fprintf(os.Stderr, "读取错误: %v\n", err)
return
}
}
fmt.Printf("读取字符数: %d\n", len(input))
}
方法4:处理超长输入(流式处理)
package main
import (
"bufio"
"fmt"
"os"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
// 设置非常大的缓冲区
maxCapacity := 10 * 1024 * 1024 // 10MB
buf := make([]byte, maxCapacity)
scanner.Buffer(buf, maxCapacity)
// 逐行处理(适合超大文件)
lineCount := 0
totalChars := 0
for scanner.Scan() {
line := scanner.Text()
lineCount++
totalChars += len(line)
// 这里可以处理每一行
fmt.Printf("第%d行: %d字符\n", lineCount, len(line))
}
if err := scanner.Err(); err != nil {
fmt.Fprintf(os.Stderr, "错误: %v\n", err)
return
}
fmt.Printf("总计: %d行, %d字符\n", lineCount, totalChars)
}
测试示例
# 生成测试数据(10万字符)
echo "$(python3 -c "print('A' * 100000)")" | go run main.go
# 或者从文件重定向
go run main.go < large_text.txt
对于超过4096字符的输入,推荐使用方法1(调整Scanner缓冲区)或方法2(io.ReadAll)。如果输入可能非常大(超过内存限制),使用方法4的流式处理更为合适。

