Go语言的第22个练习题是关于Reader接口的,你想知道这个问题的含义是什么。

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

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      // 这也是错误的..
}
英文:

Exercise: Readers

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

huangapple
  • 本文由 发表于 2015年1月8日 19:32:39
  • 转载请务必保留本文链接:https://go.coder-hub.com/27839140.html
匿名

发表评论

匿名网友

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

确定