unknwon/the-way-to-go_ZH_CN · error

no words to parse

Error message

no words to parse

What it means

Guard panics inside fields2numbers (section 13.4): panic("no words to parse") when strings.Fields(input) yields an empty slice, and panic(&ParseError{idx, field, err}) when strconv.Atoi rejects a token. The surrounding function demonstrates the recover pattern: a deferred closure converts the panic value back into a returned error via err = fmt.Errorf("pkg: %v", r).

Source

Thrown at eBook/13.4.md:58

func Parse(input string) (numbers []int, err error) {
    defer func() {
        if r := recover(); r != nil {
            var ok bool
            err, ok = r.(error)
            if !ok {
                err = fmt.Errorf("pkg: %v", r)
            }
        }
    }()

    fields := strings.Fields(input)
    numbers = fields2numbers(fields)
    return
}

func fields2numbers(fields []string) (numbers []int) {
    if len(fields) == 0 {
        panic("no words to parse")
    }
    for idx, field := range fields {
        num, err := strconv.Atoi(field)
        if err != nil {
            panic(&ParseError{idx, field, err})
        }
        numbers = append(numbers, num)
    }
    return
}
```

示例 13.5 [panic_package.go](examples/chapter_13/panic_package.go):

```go
// panic_package.go
package main

View on GitHub (pinned to 7a54d34d36)

Solutions

  1. Skip empty/blank input before parsing: trim the string and return early when strings.Fields(input) is empty
  2. Validate tokens with a loop over strconv.Atoi returning an error instead of panicking on the first bad field
  3. Keep the deferred recover wrapper so any residual panic becomes a normal error for callers
  4. In the recover branch, type-assert *ParseError to report index/field precisely instead of a generic message

Example fix

// before
func fields2numbers(fields []string) (numbers []int) {
    if len(fields) == 0 {
        panic("no words to parse")
    }
    ...
}

// after
if len(strings.Fields(input)) == 0 {
    return nil, errors.New("no words to parse")
}
Defensive patterns

Strategy: validation

Validate before calling

// pre-check the input before calling the parser
func parseable(input string) bool {
    fields := strings.Fields(input)
    if len(fields) == 0 {
        return false // would panic "no words to parse"
    }
    for _, f := range fields {
        if _, err := strconv.Atoi(f); err != nil {
            return false // would panic &ParseError
        }
    }
    return true
}

Type guard

// narrows a recovered panic value to *ParseError
func asParseError(r interface{}) (*ParseError, bool) {
    pe, ok := r.(*ParseError)
    return pe, ok
}

Try / catch

// recover-to-error wrapper, as the section itself shows
defer func() {
    if r := recover(); r != nil {
        if pe, ok := r.(*ParseError); ok {
            err = fmt.Errorf("pkg: field %d (%q): %v", pe.Index, pe.Field, pe.Err)
        } else {
            err = fmt.Errorf("pkg: %v", r)
        }
    }
}()
numbers = fields2numbers(strings.Fields(input))

Prevention

When it happens

Trigger: An input string that is empty or whitespace-only makes strings.Fields return a zero-length slice, triggering 'no words to parse'; any token such as 'foo' or '1x' fails strconv.Atoi and panics with a *ParseError carrying index, field, and underlying error.

Common situations: Reading blank lines from stdin in a loop; space-separated data files with missing or malformed columns; trailing whitespace-only input passed straight from user prompts.

Related errors


AI-assisted analysis of unknwon/the-way-to-go_ZH_CN@7a54d34d36 (2026-08-15). Data as JSON: /api/errors/e78321ab9a09de92. Report an issue: GitHub.