reader.ReadLine()在scanner.Scan()调用后未前进

The code below reads its values from this file:

2 3

1.0 2.0 3.0

-1.0 -2.0 -3.0

And should print: [ {1 2 3}, {-1 -2 -3} ]

But instead I get this:

[{2 [31 2 3]} {0 []}] strconv.ParseFloat: parsing "3.0-1.0": invalid syntax

It seems that the reader.ReadLine() stays at the same location. Is there a simpler way to scan lines, then values inside each line?

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "os"
    "strconv"
    "strings"
)

type Example struct {
    classLabel int
    attributes []float64
}

func NewExample(classLabel int, attributes []float64) *Example {
    return &Example{classLabel, attributes}
}

func readFile(path string) ([]Example, error) {

    var (
        result       []Example
        err          error
        file         *os.File
        part         []byte
        size         int
        attributeNum int
    )

    if file, err = os.Open(path); err != nil {
        return result, err
    }
    defer file.Close()

    reader := bufio.NewReader(file)
    buffer := bytes.NewBuffer(make([]byte, 0))

    if part, _, err = reader.ReadLine(); err != nil {
        return result, err
    }
    buffer.Write(part)
    newLine := buffer.String()
    fmt.Println("newLine=" + newLine)

    r := strings.NewReader(newLine)
    scanner := bufio.NewScanner(r)
    scanner.Split(bufio.ScanWords)

    if scanner.Scan() {
        size, err = strconv.Atoi(scanner.Text())
        if err != nil {
            return result, err
        }
    }
    fmt.Println("size=" + strconv.Itoa(size))

    if scanner.Scan() {
        attributeNum, err = strconv.Atoi(scanner.Text())
        if err != nil {
            return result, err
        }
    }
    fmt.Println("attributeNum=" + strconv.Itoa(attributeNum))

    result = make([]Example, size)

    var classLabel int
    var attributes []float64

    for k := 0; k < size; k++ {
        if part, _, err = reader.ReadLine(); err != nil {
            return result, err
        }
        buffer.Write(part)
        newLine := buffer.String()
        fmt.Println("newLine=" + newLine)

        r := strings.NewReader(newLine)
        scanner := bufio.NewScanner(r)
        scanner.Split(bufio.ScanWords)

        if scanner.Scan() {
            classLabel, err = strconv.Atoi(scanner.Text())
            if err != nil {
                return result, err
            }
        }
        fmt.Println("classLabel=" + strconv.Itoa(classLabel))

        for i := 0; i < attributeNum; i++ {
            var attribute float64
            if scanner.Scan() {
                attribute, err = strconv.ParseFloat(scanner.Text(), 64)
                if err != nil {
                    return result, err
                }
                attributes = append(attributes, attribute)
                fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64))
            }
        }
        result[k] = *NewExample(classLabel, attributes)
    }

    return result, scanner.Err()
}

func main() {
    example, err := readFile("test.txt")
    fmt.Println(example, err)
}

When you do this inside the for loop:

buffer.Write(part)
newLine := buffer.String()
fmt.Println("newLine=" + newLine)

The next line gets appended to buffer. That is, before the loop begins, buffer contains 2 3, and then after reading 1.0 2.0 3.0, it gets appended to buffer, so the content becomes 2 31.0 2.0 3.0, which you store in newLine. That's where things start to go sideways.

You probably want to clear the buffer before reading each new line:

buffer.Reset()
buffer.Write(part)
newLine := buffer.String()
fmt.Println("newLine=" + newLine)

But then you will have further problems still, here:

    if scanner.Scan() {
        classLabel, err = strconv.Atoi(scanner.Text())
        if err != nil {
            return result, err
        }
    }

Since the line contains 1.0 2.0 3.0, the strconf.Atoi is going to fail. I don't understand the purpose of this snippet, perhaps you can delete it (or comment out).

With the above fixed, you will still have one more problem, on this line:

          attributes = append(attributes, attribute)

Since attributes is never reset, it keeps growing. That is, after the first line, it will contain 1 2 3, and after the second line it will contain 1 2 3 -1 -2 -3. You could correct that by moving the declaration of attributes without the outer loop, like this:

    var attributes []float64
    for i := 0; i < attributeNum; i++ {
        var attribute float64
        if scanner.Scan() {
            attribute, err = strconv.ParseFloat(scanner.Text(), 64)
            if err != nil {
                return result, err
            }
            attributes = append(attributes, attribute)
            fmt.Println("attribute=" + strconv.FormatFloat(attribute, 'f', -1, 64))
        }
    }