带有 fmt 的意外 EOF。扫描器

unexpected EOF with fmt.Scanner

提问人:Zombo 提问时间:5/27/2021 最后编辑:Zombo 更新时间:5/30/2021 访问量:1246

问:

如果我想扫描一个字符串,我可以这样做:

package main

import (
   "fmt"
   "strings"
)

func main() {
   r := strings.NewReader("west north east")
   for {
      var s string
      _, e := fmt.Fscan(r, &s)
      fmt.Printf("%q %v\n", s, e)
      if e != nil { break }
   }
}

结果:

"west" <nil>
"north" <nil>
"east" <nil>
"" EOF

我最近发现了 [1],所以我想我会尝试实现 它。我想出了这个:fmt.Scanner

package main

import (
   "fmt"
   "strings"
)

type comma struct { tok string }

func (c *comma) Scan(state fmt.ScanState, verb rune) error {
   tok, err := state.Token(false, func(r rune) bool {
      return r != ','
   })
   if err != nil {
      return err
   }
   if _, _, err := state.ReadRune(); err != nil {
      if len(tok) == 0 {
         return err
      }
   }
   c.tok = string(tok)
   return nil
}

func main() {
   r := strings.NewReader("west,north,east")
   for {
      var c comma
      _, e := fmt.Fscan(r, &c)
      fmt.Printf("%q %v\n", c.tok, e)
      if e != nil { break }
   }
}

结果:

"west" <nil>
"north" <nil>
"east" <nil>
"" unexpected EOF

所以结果非常接近,但困扰我的是.是 有可能只是得到一个有定制的常客吗?我在做什么 这里出了点问题,还是这是一个错误?unexpected EOFEOFfmt.Scanner

  1. https://golang.org/pkg/fmt#Scanner
字符串 go 令牌 eof

评论

1赞 leaf bebop 5/27/2021
我认为这在当前版本的 Go 中是不可能的。请参见:golang.org/src/fmt/scan.go?s=2653:2699#L961

答:

1赞 Zombo 5/27/2021 #1

多亏了名单上的伊恩·兰斯·泰勒(Ian Lance Taylor),他建议错误而不是.在 Go 代码中,调用一个函数 ,而函数又调用一个函数 [1]。最后一个函数 用于将任何错误转换为常规错误。该程序提供 我的原始示例的同等输出:golang-nutspanicreturnFscandoScanerrorHandlerrecoverpanic

package main

import (
   "fmt"
   "strings"
)

type comma struct { tok string }

func (c *comma) Scan(state fmt.ScanState, verb rune) error {
   tok, err := state.Token(false, func(r rune) bool {
      return r != ','
   })
   if err != nil { return err }
   if _, _, err := state.ReadRune(); err != nil {
      if len(tok) == 0 {
         panic(err)
      }
   }
   c.tok = string(tok)
   return nil
}

func main() {
   r := strings.NewReader("west,north,east")
   for {
      var c comma
      _, err := fmt.Fscan(r, &c)
      fmt.Printf("%q %v\n", c.tok, err)
      if err != nil { break }
   }
}
  1. https://github.com/golang/go/blob/go1.16.4/src/fmt/scan.go#L1056-L1067