如何使用fmt.Sscan将整数解析为数组?

I'm trying to scan a list of integers from a string into an array (or alternatively, a slice)

package main

import "fmt"

func main() {
    var nums [5]int
    n, _ := fmt.Sscan("1 2 3 4 5", &nums)  // doesn't work
    fmt.Println(nums)
}

What do I need to pass as second argument to Sscan in order for this to work?

I know I could pass nums[0], nums[1] ... etc., but I'd prefer a single argument.

I don't think this is possible as a convenient one-liner. As Sscan takes ...interface{}, you would need to pass slice of interfaces as well, hence converting your array first:

func main() {
    var nums [5]int

    // Convert to interfaces
    xnums := make([]interface{}, len(nums))
    for n := range nums {
        xnums[n] = &nums[n]
    }

    n, err := fmt.Sscan("1 2 3 4 5", xnums...)
    if err != nil {
        fmt.Printf("field %d: %s
", n+1, err)
    }

    fmt.Println(nums)
}

http://play.golang.org/p/1X28J7JJwl

Obviously you could mix different types in your interface array, so it would make the scanning of more complex string easier. For simply space-limited integers, you might be better using strings.Split or bufio.Scanner along with strconv.Atoi.

To allow this to work on more than just hard-coded strings, it's probably better to use a bufio.Scanner, and an io.Reader interface to do this:

package main

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

func scanInts(r io.Reader) ([]int, error) {
    s := bufio.NewScanner(r)
    s.Split(bufio.ScanWords)
    var ints []int
    for s.Scan() {
        i, err := strconv.Atoi(s.Text())
        if err != nil {
            return ints, err
        }
        ints = append(ints, i)
    }
    return ints, s.Err()
}

func main() {
    input := "1 2 3 4 5"
    ints, err := scanInts(strings.NewReader(input))
    if err != nil {
        fmt.Println(err)
    }
    fmt.Println(ints)
}

Produces:

[1 2 3 4 5]

Playground

Unless you're trying to use Sscann specifically you can also try this as an alternative:

  • split the input string by spaces
  • iterate the resulting array
  • convert each string into an int
  • store the resulting value into an int slice

Like this:

package main

import (
    "fmt"
    "strconv"
    "strings"
)

func main() {

    nums := make([]int, 0)
    for _, s := range strings.Split("1 2 3 4 5", " ") {
        i, e := strconv.Atoi(s)
        if e != nil {
            i = 0 // that was not a number, default to 0
        }
        nums = append(nums, i)
    }
    fmt.Println(nums)
}

http://play.golang.org/p/rCZl46Ixd4