英文:
Tour of Go exercise #22: Reader, what does the question mean?
问题
实现一个读取器类型,它会无限地发出 ASCII 字符 'A'。
我不理解这个问题,如何发出字符 'A'?应该将该字符设置到哪个变量中?
这是我尝试过的:
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
// TODO: 为 MyReader 添加一个 Read([]byte) (int, error) 方法。
func main() {
reader.Validate(MyReader{}) // 这个函数期望什么?
}
func (m MyReader) Read(b []byte) (i int, e error) {
b = append(b, 'A') // 这是错误的..
return 1, nil // 这也是错误的..
}
英文:
Implement a Reader type that emits an infinite stream of the ASCII character 'A'.
I don't understand the question, how to emit character 'A'? into which variable should I set that character?
Here's what I tried:
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
// TODO: Add a Read([]byte) (int, error) method to MyReader.
func main() {
reader.Validate(MyReader{}) // what did this function expect?
}
func (m MyReader) Read(b []byte) (i int, e error) {
b = append(b, 'A') // this is wrong..
return 1, nil // this is also wrong..
}
答案1
得分: 60
啊,我明白了XD
我认为更好的说法是:将[]byte
中的所有值重写为'A'
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
// TODO: 为 MyReader 添加一个 Read([]byte) (int, error) 方法。
func (m MyReader) Read(b []byte) (i int, e error) {
for x := range b {
b[x] = 'A'
}
return len(b), nil
}
func main() {
reader.Validate(MyReader{})
}
英文:
Ah I understand XD
I think it would be better to say: "rewrite all values in []byte
into 'A'
s"
package main
import "golang.org/x/tour/reader"
type MyReader struct{}
// TODO: Add a Read([]byte) (int, error) method to MyReader.
func (m MyReader) Read(b []byte) (i int, e error) {
for x := range b {
b[x] = 'A'
}
return len(b), nil
}
func main() {
reader.Validate(MyReader{})
}
答案2
得分: 4
一个io.Reader.Read
的作用是将从其源读取的数据写入给定的内存位置。
要实现一个流的'A'
,该函数必须将给定的内存位置写入'A'
值。
不需要填充输入中提供的整个切片,它可以决定写入多少字节的输入切片(Read将最多读取len(p)字节到p中
),它必须返回该数字以指示给消费者处理的数据长度。
按照惯例,io.Reader
通过返回io.EOF
错误来指示其结束。如果读取器不返回错误,则它将作为数据的无限源对其消费者进行操作,消费者永远无法检测到退出条件。
请注意,调用返回0字节
读取的Read
可能会发生,并且不表示任何特殊情况,调用者应将返回的0和nil视为表示什么都没有发生;
这使得这个非解决方案 https://play.golang.org/p/aiUyc4UDYi2 在超时时失败。
关于这一点,这里提供的解决方案 https://stackoverflow.com/a/68077578/4466350 return copy(b, "A"), nil
真的很好。它写入了所需的最小值,并且使用了内置的和语法工具,而且它从不返回错误。
英文:
An io.Reader.Read
role is to write a given memory location with data read from its source.
To implement a stream of 'A'
, the function must write given memory location with 'A'
values.
It is not required to fill in the entire slice provided in input, it can decide how many bytes of the input slice is written (Read reads up to len(p) bytes into p
), it must return that number to indicate to the consumer the length of data to process.
By convention an io.Reader
indicates its end by returning an io.EOF
error. If the reader does not return an error, it behaves as an infinite source of data to its consumer which can never detect an exit condition.
Note that a call to Read
that returns 0 bytes
read can happen and does not indicate anything particular, Callers should treat a return of 0 and nil as indicating that nothing happened;
Which makes this non-solution https://play.golang.org/p/aiUyc4UDYi2 fails with a timeout.
In regard to that, the solution provided here https://stackoverflow.com/a/68077578/4466350 return copy(b, "A"), nil
is really just right. It writes the minimum required, with an elegant use of built-ins and syntax facilities, and it never returns an error.
答案3
得分: 1
func (s MyReader) Read(b []byte) (int, error) {
b[0] = byte('A')
return 1, nil
}
最简单的一个:
func (s MyReader) Read(b []byte) (int, error) {
b[0] = byte('A')
return 1, nil
}
英文:
Simplest one:
func (s MyReader) Read(b []byte) (int, error) {
b[0] = byte('A')
return 1, nil
}
答案4
得分: 1
你可以推广这个想法,创建一个永远读取相同字节值的永久读取器alwaysReader
(它永远不会返回EOF):
package readers
type alwaysReader struct {
value byte
}
func (r alwaysReader) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = r.value
}
return len(p), nil
}
func NewAlwaysReader(value byte) alwaysReader {
return alwaysReader{value}
}
NewAlwaysReader()
是alwaysReader
的构造函数(它没有被导出)。调用NewAlwaysReader('A')
的结果是一个读取器,你将永远从中读取'A'
。
下面是对alwaysReader
的一个说明性单元测试:
package readers_test
import (
"bytes"
"io"
"readers"
"testing"
)
func TestEmptyReader(t *testing.T) {
const numBytes = 128
const value = 'A'
buf := bytes.NewBuffer(make([]byte, 0, numBytes))
reader := io.LimitReader(readers.NewAlwaysReader(value), numBytes)
n, err := io.Copy(buf, reader)
if err != nil {
t.Fatal("copy failed:", err)
}
if n != numBytes {
t.Errorf("%d bytes read but %d expected", n, numBytes)
}
for i, elem := range buf.Bytes() {
if elem != value {
t.Errorf("byte at position %d has not the value %v but %v", i, value, elem)
}
}
}
由于我们可以无限读取alwaysReader
,所以我们需要使用io.LimitReader
对其进行修饰,以便最多从中读取numBytes
个字节。否则,由于io.Copy()
的缘故,bytes.Buffer
最终会耗尽内存来重新分配其内部缓冲区。
请注意,对于alwaysReader
的以下Read()
实现也是有效的:
func (r alwaysReader) Read(p []byte) (n int, err error) {
if len(p) > 0 {
p[0] = r.value
return 1, nil
}
return 0, nil
}
前一个Read()
实现将整个字节切片填充为相同的字节值,而后一个实现只写入一个字节。
英文:
You can generalize the idea to create an eternal reader, alwaysReader
, from which you always read the same byte value over and over (it never results in EOF):
package readers
type alwaysReader struct {
value byte
}
func (r alwaysReader) Read(p []byte) (n int, err error) {
for i := range p {
p[i] = r.value
}
return len(p), nil
}
func NewAlwaysReader(value byte) alwaysReader {
return alwaysReader { value }
}
NewAlwaysReader()
is the constructor for alwaysReader
(which isn't exported). The result of NewAlwaysReader('A')
is a reader from whom you will always read 'A'
.
A clarifying unit test for alwaysReader
:
package readers_test
import (
"bytes"
"io"
"readers"
"testing"
)
func TestEmptyReader(t *testing.T) {
const numBytes = 128
const value = 'A'
buf := bytes.NewBuffer(make([]byte, 0, numBytes))
reader := io.LimitReader(readers.NewAlwaysReader(value), numBytes)
n, err := io.Copy(buf, reader)
if err != nil {
t.Fatal("copy failed: %w")
}
if n != numBytes {
t.Errorf("%d bytes read but %d expected", n, numBytes)
}
for i, elem := range buf.Bytes() {
if elem != value {
t.Errorf("byte at position %d has not the value %v but %v", i, value, elem)
}
}
}
Since we can read from the alwaysReader
forever, we need to decorate it with a io.LimitReader
so that we end up reading at most numBytes
from it. Otherwise, the bytes.Buffer
will eventually run out of memory for reallocating its internal buffer because of io.Copy()
.
Note that the following implementation of Read()
for alwaysReader
is also valid:
func (r alwaysReader) Read(p []byte) (n int, err error) {
if len(p) > 0 {
p[0] = r.value
return 1, nil
}
return 0, nil
}
The former Read()
implementation fills the whole byte slice with the byte value, whereas the latter writes a single byte.
答案5
得分: 0
所谓的答案对我来说不起作用,即使没有拼写错误。
无论我怎么尝试,该字符串都无法放入b中。
func (r MyReader) Read(b []byte) (int, error) {
return copy(b, "A"), nil
}
英文:
The alleged answer is didn't work for me, even without the typos.
Try as I did, that string would not go into b.
func (r MyReader) Read(b []byte) (int, error) {
return copy(b, "A"), nil
}
答案6
得分: 0
我的解决方案:一次只添加一个字节,使用闭包存储索引i
。
package main
import (
"golang.org/x/tour/reader"
)
type MyReader struct{}
func (mr MyReader) Read(b []byte) (int, error) {
i := 0
p := func() int {
b[i] = 'A'
i += 1
return i
}
return p(), nil
}
func main() {
reader.Validate(MyReader{})
}
英文:
My solution: just add one byte at a time, store the index i
using closure.
package main
import (
"golang.org/x/tour/reader"
)
type MyReader struct{}
func (mr MyReader) Read(b []byte) (int, error) {
i := 0
p := func () int {
b[i] = 'A'
i += 1
return i
}
return p(), nil
}
func main() {
reader.Validate(MyReader{})
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论