Golang中Scanner使用问题解析

Golang中Scanner使用问题解析 123

我的程序无法从scan函数获取"floatvalue"的值。 我相当确定我的代码是正确的,但由于某种原因,它没有正确执行。 我是不是做错了什么? ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

Visual Studio Code

版本: 1.48.1 (用户安装)

提交: 3dd905126b34dcd4de81fa624eb3a8cbe7485f13

日期: 2020-08-19T17:12:13.244Z

Electron: 7.3.2

Chrome: 78.0.3904.130

Node.js: 12.8.1

V8: 7.8.279.23-electron.0

操作系统: Windows_NT x64 10.0.18362

名称: Go

ID: golang.go

描述: Visual Studio Code 的丰富 Go 语言支持

版本: 0.16.


更多关于Golang中Scanner使用问题解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html

9 回复

如何检查返回值

更多关于Golang中Scanner使用问题解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


抱歉,我是个新手,这该怎么做?

情况依旧,我已经发现了一个错误,所以不用担心这个,谢谢。

那么,如果你添加了错误检查,这会如何改变程序的行为或输出呢?

你具体想做什么?

检查返回值吗?

复制粘贴代码而不是贴截图吗?

描述问题而不是只放一张什么都不说的图片吗?

你检查过 fmt.Scan 的返回值吗?

这可比你用的 Chrome、Electron 或 VSCode 版本重要多了……

另外,或许应该把代码以文本形式放在代码块里,而不是贴代码的截图。

fmt.Scan 返回两个值。

第一个值是它成功解析的项目数量,第二个值是一个错误值。

如果第一个值小于你传递给 fmt.Scan 的参数数量,那么说明出现了问题,并且另一个返回值将是非 nil 的。在实践中,大多数人只检查错误值,而不是已解析参数的数量,但会打印/记录该数量用于调试目的。

_, err := fmt.Scan(&floatvalue)
if err != nil {
  panic(err)
}

从图片中的代码来看,问题在于Scanner的缓冲区大小限制。当输入的数据超过默认缓冲区大小时,Scan()方法会返回false

以下是问题分析和解决方案:

问题分析

bufio.Scanner默认的缓冲区大小为4096字节(4KB)。当输入的数据超过这个大小时,Scan()会返回false并停止扫描,导致无法读取完整的"floatvalue"值。

解决方案

方案1:增加缓冲区大小

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    const input = `1234567890...` // 很长的输入数据
    
    scanner := bufio.NewScanner(strings.NewReader(input))
    
    // 增加缓冲区大小到1MB
    buf := make([]byte, 0, 64*1024)
    scanner.Buffer(buf, 1024*1024)
    
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Println("扫描错误:", err)
    }
}

方案2:使用bufio.Reader替代

package main

import (
    "bufio"
    "fmt"
    "io"
    "strings"
)

func main() {
    const input = `1234567890...` // 很长的输入数据
    
    reader := bufio.NewReader(strings.NewReader(input))
    
    for {
        line, err := reader.ReadString('\n')
        if err != nil {
            if err == io.EOF {
                break
            }
            fmt.Println("读取错误:", err)
            return
        }
        fmt.Print(line)
    }
}

方案3:分块读取

package main

import (
    "bufio"
    "fmt"
    "strings"
)

func main() {
    const input = `1234567890...` // 很长的输入数据
    
    scanner := bufio.NewScanner(strings.NewReader(input))
    
    // 自定义分割函数,按需处理长行
    scanner.Split(func(data []byte, atEOF bool) (advance int, token []byte, err error) {
        // 这里可以实现自定义的分割逻辑
        // 例如:按最大长度分割
        maxLen := 4096
        if len(data) >= maxLen {
            return maxLen, data[:maxLen], nil
        }
        
        if atEOF && len(data) > 0 {
            return len(data), data, nil
        }
        
        // 请求更多数据
        return 0, nil, nil
    })
    
    for scanner.Scan() {
        fmt.Println(scanner.Text())
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Println("扫描错误:", err)
    }
}

错误检查

在你的代码中添加错误检查可以明确问题:

if err := scanner.Err(); err != nil {
    fmt.Printf("扫描错误: %v\n", err)
    // 如果看到 "bufio.Scanner: token too long" 错误
    // 说明需要增加缓冲区大小
}

主要问题确实是缓冲区大小不足。使用scanner.Buffer()方法增加缓冲区大小是最直接的解决方案。

回到顶部