Go:将数据从 io.Reader 复制到 io.Writer 具有睡眠超时的实现,空写入
Go: Copy data from io.Reader to io.Writer implementations with sleep timeout, empty Writes
-编辑-
这不是拼写错误造成的,它是可重现的,与 Whosebug 给出的指定相反。提供的代码是专门为这个问题编写的自包含示例(问题就在代码中,你所要做的就是 运行 它来重现问题...)
此外,这正是我遇到的确切问题和我需要的确切解决方案,但在提出问题之前我没有在 Whosebug 上找到。答案来自 IRC 上的一次对话,我已将解决方案转发给像我一样可能遇到同样问题的其他人。这是非常相关的 Q/A,当然可以帮助未来的读者。
谢谢
-编辑-
我正在尝试将数据从 io.Reader 实现复制到 io.Writer 实现,并在下一次迭代之前延迟 (time.Sleep)。理想情况下,我想控制进程(即 io.Copy 并不理想,因为我可能想在读取和写入之间执行一些操作)。
无论如何,在下面的代码中尝试了 4 种方法,它应该 运行 在 go.dev/play
中。除了空字符串之外,我无法获得任何 Write 方法,尽管 Write 的所有方法都报告了正确的写入字节数(与 Read 报告的相同)。我可能遗漏了一些基本的东西,但是任何 help/explanation 都非常感谢,因为我很困惑。
以下代码包含 4 种不同方法的注释和函数,用于将数据从 io.Reader 的自定义实现复制和记录到 io.Writer,并在指定延迟(time.Sleep)之前下一次迭代。您可以 comment/uncomment 下面的所需函数来观察结果。
package main
import (
"bufio"
"fmt"
"io"
"log"
"math/rand"
"time"
)
// READ
type MyReader struct{}
func (r *MyReader) Read(p []byte) (read int, err error) {
someString := fmt.Sprintf("testing-%d", rand.Int())
p = []byte(someString)
read = len(p)
log.Printf("io read %d bytes: %s\n", read, string(p))
return read, io.EOF
}
// WRITE
type MyWriter struct{}
func (w *MyWriter) Write(p []byte) (wrote int, err error) {
wrote = len(p)
log.Printf("io wrote %d bytes: %s\n", wrote, string(p))
return
}
// MAIN
func main() {
// The following contains comments and functions for 4 different approaches to copying and logging data from
// custom implementations of io.Reader to an io.Writer with a specified delay (time.Sleep) before the next
// iteration. You may comment/uncomment the desired function below to observe the results.
// AutoIoCopy - Approach 1) io.Copy
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and the MyWriter.Write method of the io.Writer implementation
// is executed, but the output logged by MyWriter.Write is empty instead of the expected string reported by the
// MyReader.Read log.
//
AutoIoCopy()
// ReadBytesApproach - Approach 2) Using ReadBytes('\n')
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//ReadBytesApproach()
// ReadLineApproach - Approach 3) Using ReadLine()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//ReadLineApproach()
// WriteToApproach - Approach 4) Using WriteTo()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//WriteToApproach()
}
// Approaches:
// AutoIoCopy - Approach 1) io.Copy
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and the MyWriter.Write method of the io.Writer implementation
// is executed, but the output logged by MyWriter.Write is empty instead of the expected string reported by the
// MyReader.Read log.
//
func AutoIoCopy() {
reader := MyReader{}
writer := MyWriter{}
for {
_, _ = io.Copy(&writer, &reader)
time.Sleep(1000 * time.Millisecond)
}
}
// ReadBytesApproach - Approach 2) Using ReadBytes('\n')
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called but the Write method of MyWriter io.Writer implementation
// is never executed, it is skipped and another Read occurs
//
func ReadBytesApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
// Using ReadBytes('\n')
readBytes, err := bufRead.ReadBytes('\n')
if err != nil {
switch err {
case io.EOF:
log.Printf("io.EOF detected\n")
wrote, err := bufWrite.Write(readBytes)
if err != nil {
log.Printf("error writing: %s\n", err)
}
convertedValue := string(readBytes)
log.Printf("bufio wrote %d bytes: %s\n", wrote, convertedValue)
break
default:
log.Printf("bufio error reading: %s\n", err.Error())
break
}
} else {
log.Printf("no error, continue to read\n")
}
time.Sleep(1000 * time.Millisecond)
}
}
// ReadLineApproach - Approach 3) Using ReadLine()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called but the Write method of MyWriter io.Writer implementation
// is never executed, it is skipped and another Read occurs
//
func ReadLineApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
// Using ReadLine()
readBytes, _, err := bufRead.ReadLine()
if err != nil {
switch err {
case io.EOF:
log.Printf("io.EOF detected\n")
wrote, err := bufWrite.Write(readBytes)
if err != nil {
log.Printf("error writing: %s\n", err)
}
convertedValue := string(readBytes)
log.Printf("bufio wrote %d bytes: %s\n", wrote, convertedValue)
break
default:
log.Printf("bufio error reading: %s\n", err.Error())
break
}
} else {
log.Printf("no error, continue to read\n")
}
time.Sleep(1000 * time.Millisecond)
}
}
// WriteToApproach - Approach 4) Using WriteTo()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that neither the bufio.Write or the Write method of MyWriter io.Writer implementation is executed,
// it is skipped and another Read occurs
//
func WriteToApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
wrote, _ := bufRead.WriteTo(bufWrite)
log.Printf("bufio wrote %d bytes\n", wrote)
time.Sleep(1000 * time.Millisecond)
}
}
问题出在 MyReader.Read
方法中
行
p = []byte(someString)
应该是
read = copy(p, someString)
-编辑-
这不是拼写错误造成的,它是可重现的,与 Whosebug 给出的指定相反。提供的代码是专门为这个问题编写的自包含示例(问题就在代码中,你所要做的就是 运行 它来重现问题...)
此外,这正是我遇到的确切问题和我需要的确切解决方案,但在提出问题之前我没有在 Whosebug 上找到。答案来自 IRC 上的一次对话,我已将解决方案转发给像我一样可能遇到同样问题的其他人。这是非常相关的 Q/A,当然可以帮助未来的读者。
谢谢
-编辑-
我正在尝试将数据从 io.Reader 实现复制到 io.Writer 实现,并在下一次迭代之前延迟 (time.Sleep)。理想情况下,我想控制进程(即 io.Copy 并不理想,因为我可能想在读取和写入之间执行一些操作)。
无论如何,在下面的代码中尝试了 4 种方法,它应该 运行 在 go.dev/play
中。除了空字符串之外,我无法获得任何 Write 方法,尽管 Write 的所有方法都报告了正确的写入字节数(与 Read 报告的相同)。我可能遗漏了一些基本的东西,但是任何 help/explanation 都非常感谢,因为我很困惑。
以下代码包含 4 种不同方法的注释和函数,用于将数据从 io.Reader 的自定义实现复制和记录到 io.Writer,并在指定延迟(time.Sleep)之前下一次迭代。您可以 comment/uncomment 下面的所需函数来观察结果。
package main
import (
"bufio"
"fmt"
"io"
"log"
"math/rand"
"time"
)
// READ
type MyReader struct{}
func (r *MyReader) Read(p []byte) (read int, err error) {
someString := fmt.Sprintf("testing-%d", rand.Int())
p = []byte(someString)
read = len(p)
log.Printf("io read %d bytes: %s\n", read, string(p))
return read, io.EOF
}
// WRITE
type MyWriter struct{}
func (w *MyWriter) Write(p []byte) (wrote int, err error) {
wrote = len(p)
log.Printf("io wrote %d bytes: %s\n", wrote, string(p))
return
}
// MAIN
func main() {
// The following contains comments and functions for 4 different approaches to copying and logging data from
// custom implementations of io.Reader to an io.Writer with a specified delay (time.Sleep) before the next
// iteration. You may comment/uncomment the desired function below to observe the results.
// AutoIoCopy - Approach 1) io.Copy
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and the MyWriter.Write method of the io.Writer implementation
// is executed, but the output logged by MyWriter.Write is empty instead of the expected string reported by the
// MyReader.Read log.
//
AutoIoCopy()
// ReadBytesApproach - Approach 2) Using ReadBytes('\n')
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//ReadBytesApproach()
// ReadLineApproach - Approach 3) Using ReadLine()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//ReadLineApproach()
// WriteToApproach - Approach 4) Using WriteTo()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and reports written bytes, but the Write method of MyWriter
// io.Writer implementation is never executed, it is skipped and another Read occurs
//
//WriteToApproach()
}
// Approaches:
// AutoIoCopy - Approach 1) io.Copy
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called and the MyWriter.Write method of the io.Writer implementation
// is executed, but the output logged by MyWriter.Write is empty instead of the expected string reported by the
// MyReader.Read log.
//
func AutoIoCopy() {
reader := MyReader{}
writer := MyWriter{}
for {
_, _ = io.Copy(&writer, &reader)
time.Sleep(1000 * time.Millisecond)
}
}
// ReadBytesApproach - Approach 2) Using ReadBytes('\n')
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called but the Write method of MyWriter io.Writer implementation
// is never executed, it is skipped and another Read occurs
//
func ReadBytesApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
// Using ReadBytes('\n')
readBytes, err := bufRead.ReadBytes('\n')
if err != nil {
switch err {
case io.EOF:
log.Printf("io.EOF detected\n")
wrote, err := bufWrite.Write(readBytes)
if err != nil {
log.Printf("error writing: %s\n", err)
}
convertedValue := string(readBytes)
log.Printf("bufio wrote %d bytes: %s\n", wrote, convertedValue)
break
default:
log.Printf("bufio error reading: %s\n", err.Error())
break
}
} else {
log.Printf("no error, continue to read\n")
}
time.Sleep(1000 * time.Millisecond)
}
}
// ReadLineApproach - Approach 3) Using ReadLine()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that the bufio.Write method is called but the Write method of MyWriter io.Writer implementation
// is never executed, it is skipped and another Read occurs
//
func ReadLineApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
// Using ReadLine()
readBytes, _, err := bufRead.ReadLine()
if err != nil {
switch err {
case io.EOF:
log.Printf("io.EOF detected\n")
wrote, err := bufWrite.Write(readBytes)
if err != nil {
log.Printf("error writing: %s\n", err)
}
convertedValue := string(readBytes)
log.Printf("bufio wrote %d bytes: %s\n", wrote, convertedValue)
break
default:
log.Printf("bufio error reading: %s\n", err.Error())
break
}
} else {
log.Printf("no error, continue to read\n")
}
time.Sleep(1000 * time.Millisecond)
}
}
// WriteToApproach - Approach 4) Using WriteTo()
//
// Expected is to read and log the correct value (generated in the method)
// then write the value (output another log)
//
// Actual is that neither the bufio.Write or the Write method of MyWriter io.Writer implementation is executed,
// it is skipped and another Read occurs
//
func WriteToApproach() {
reader := MyReader{}
writer := MyWriter{}
bufRead := bufio.NewReader(&reader)
bufWrite := bufio.NewWriter(&writer)
for {
wrote, _ := bufRead.WriteTo(bufWrite)
log.Printf("bufio wrote %d bytes\n", wrote)
time.Sleep(1000 * time.Millisecond)
}
}
问题出在 MyReader.Read
方法中
行
p = []byte(someString)
应该是
read = copy(p, someString)