Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

golang reader.Read() can arrived EOF, but reader.ReadAt() read same data in dead loop way, not arrived EOF?

I’m trying to learn the diff in io.Reader.Read() and io.Reader.ReadAt();
And I write two example, the first is io.Reader.Read():

    reader := strings.NewReader("some text heresome text heres, ome text heresome text heresome text here")

    buf := make([]byte, 64)

    i := 0
    for {
        i++
        if i > 10 {
            break
        }

        n, err := reader.Read(buf)

        if n > 0 {
            fmt.Println(string(buf[:n]))
        }

        fmt.Println(err)

        if err == io.EOF {
            fmt.Println("All content is over...")
            break
        } else if err != nil {
            panic(err.Error())
        }
    }

and the output is:

some text heresome text heres, ome text heresome text heresome t
<nil>
ext here
<nil>
EOF
All content is over...

the second example just replace the Read() to ReadAt():

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

    reader := strings.NewReader("some text heresome text heres, ome text heresome text heresome text here")

    buf := make([]byte, 64)

    i := 0
    for {
        i++
        if i > 10 {
            break
        }

        n, err := reader.ReadAt(buf, 2)

        if n > 0 {
            fmt.Println(string(buf[:n]))
        }

        fmt.Println(err)

        if err == io.EOF {
            fmt.Println("All content is over...")
            break
        } else if err != nil {
            panic(err.Error())
        }
    }

And the result unexpected not arrived the EOF, and deep loop occured if I cancel times limit:
output:

me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>
me text heresome text heres, ome text heresome text heresome tex
<nil>

I expected the second example code output similar with first code example, just offset 2 bytes. but why the code into dead loop?

>Solution :

Reading from an io.Reader using its Read() method, the reader’s internal pointer (offset) advances by the number of read (returned) bytes. So the next Read() call will read bytes from the current offset.

When you call ReadAt() method, you explicit provide the offset to read at, the internal pointer / offset of the io.Reader is not used. And since the buffer you read into is smaller than the available data of the source reader (starting at the given offset), you won’t get an io.EOF, and you’ll just read the same data from the same offset over and over again.

Note that if you increase the buffer:

buf := make([]byte, 164)

This way all the data available at the source can be read into it, and you’ll get an EOF immediately (try it on the Go Playground):

me text heresome text heres, ome text heresome text heresome text here
EOF
All content is over...
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading