Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fmt: Scan returns "unexpected EOF" instead of io.EOF when arguments have a custom Scan method #17246

kaisuke opened this issue Sep 27, 2016 · 4 comments


Copy link

@kaisuke kaisuke commented Sep 27, 2016

What version of Go are you using (go version)?

go version go1.7.1 linux/amd64

What operating system and processor architecture are you using (go env)?

GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build253151644=/tmp/go-build -gno-record-gcc-switches"

What did you do?

What did you expect to see?

1 <nil> 42
1 <nil> 42
0 EOF 0
0 EOF 0

What did you see instead?

1 <nil> 42
1 <nil> 42
0 EOF 0
0 unexpected EOF 0
Copy link

@minux minux commented Sep 27, 2016

Copy link

@kaisuke kaisuke commented Sep 27, 2016

Thanks. I don't think it's a math/big problem, because I get io.ErrUnexpectedEOF with my own type too:

Here, my Scanner returns io.EOF, but fmt.Sscan changes it to io.ErrUnexpectedEOF. I don't understand the rationale behind this. Looking at the comments for the two error values, I feel that io.EOF is appropriate for my two examples because we're not encountering EOF in the middle of a data structure.

Copy link

@minux minux commented Sep 27, 2016

@quentinmit quentinmit added this to the Go1.8Maybe milestone Oct 3, 2016
@rsc rsc modified the milestones: Go1.9, Go1.8Maybe Nov 2, 2016
@bradfitz bradfitz modified the milestones: Go1.10, Go1.9 Jun 7, 2017
@rsc rsc modified the milestones: Go1.10, Go1.11 Nov 22, 2017
@gopherbot gopherbot modified the milestones: Go1.11, Unplanned May 23, 2018
Copy link

@89z 89z commented May 27, 2021

Thanks to Ian Lance Taylor on the golang-nuts list, he suggested to panic the error instead of return. In the Go code, Fscan calls a function doScan, which in turn calls a function errorHandler [1]. This last function uses recover to turn any panic into regular error. Example:

package main

import (

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 {
   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 }


"west" <nil>
"north" <nil>
"east" <nil>
"" EOF
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
7 participants