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

huangapple go评论70阅读模式
英文:

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

问题

我正在尝试学习io.Reader.Read()io.Reader.ReadAt()之间的区别,并编写了两个示例。第一个示例使用了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())
    }
}

输出结果为:

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

第二个示例只是将Read()替换为ReadAt()

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())
    }
}

结果出乎意料,没有达到EOF,并且如果取消次数限制,会发生深层循环。输出结果为:

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>

我期望第二个示例的输出与第一个示例的代码类似,只是偏移了2个字节。但为什么代码进入了死循环呢?

英文:

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(&quot;some text heresome text heres, ome text heresome text heresome text here&quot;)

	buf := make([]byte, 64)

	i := 0
	for {
		i++
		if i &gt; 10 {
			break
		}

		n, err := reader.Read(buf)

		if n &gt; 0 {
			fmt.Println(string(buf[:n]))
		}

		fmt.Println(err)

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

and the output is:

some text heresome text heres, ome text heresome text heresome t
&lt;nil&gt;
ext here
&lt;nil&gt;
EOF
All content is over...

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

	reader := strings.NewReader(&quot;some text heresome text heres, ome text heresome text heresome text here&quot;)

	buf := make([]byte, 64)

	i := 0
	for {
		i++
		if i &gt; 10 {
			break
		}

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

		if n &gt; 0 {
			fmt.Println(string(buf[:n]))
		}

		fmt.Println(err)

		if err == io.EOF {
			fmt.Println(&quot;All content is over...&quot;)
			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
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;
me text heresome text heres, ome text heresome text heresome tex
&lt;nil&gt;

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

答案1

得分: 3

使用Read()方法从io.Reader中读取数据时,读取器的内部指针(偏移量)会根据读取的字节数前进。下一次调用Read()方法将从新调整后的偏移量处读取字节。

当调用ReadAt()方法时,您需要显式提供要读取的偏移量,不使用io.Reader的内部指针/偏移量。由于您读取到的缓冲区比源读取器中可用的数据(从给定的偏移量开始)要小,因此您不会得到io.EOF,而是会一遍又一遍地读取相同偏移量处的相同数据。

请注意,如果您增加缓冲区大小:

buf := make([]byte, 164)

这样可以将源中的所有可用数据都读取到其中,并且您将立即得到一个EOF(在Go Playground上尝试一下):

me text heresome text heresome text heresome text here
EOF
All content is over...
英文:

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

When you call ReadAt() method, you explicitly 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...

huangapple
  • 本文由 发表于 2022年8月25日 18:22:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/73485857.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定