是否io.ReaderAt可以从 的实现中创建该实现而io.Reader无需先读入 a[]byte或string?
是的,这是可能的。正如我在上面的评论中提到的,实现是有限的,因为你不能向后搜索,也不能重新阅读已经阅读过的部分。
这是一个示例实现:
type unbufferedReaderAt struct {
R io.Reader
N int64
}
func NewUnbufferedReaderAt(r io.Reader) io.ReaderAt {
return &unbufferedReaderAt{R: r}
}
func (u *unbufferedReaderAt) ReadAt(p []byte, off int64) (n int, err error) {
if off < u.N {
return 0, errors.New("invalid offset")
}
diff := off - u.N
written, err := io.CopyN(ioutil.Discard, u.R, diff)
u.N += written
if err != nil {
return 0, err
}
n, err = u.R.Read(p)
u.N += int64(n)
return
}
Run Code Online (Sandbox Code Playgroud)
用法示例:
s := strings.NewReader("hello world")
var b [5]byte
ura := NewUnbufferedReaderAt(s)
if _, err := ura.ReadAt(b[:], 0); err != nil {
panic(err)
}
fmt.Printf("%s\n", b[:]) // prints "hello"
/*
if _, err := ura.ReadAt(b[:], 0); err != nil {
panic(err) // panics
}
fmt.Printf("%s\n", b[:])
*/
if _, err := ura.ReadAt(b[:], 6); err != nil {
panic(err)
}
fmt.Printf("%s\n", b[:]) // prints "world"
Run Code Online (Sandbox Code Playgroud)
像下面这样的东西。Notebytes.Reader实现了ReadAt(...)方法/函数:https : //golang.org/pkg/bytes/#Reader.ReadAt。所以这条线bytes.NewReader基本上就是你要找的东西。
获得bytes.Reader:
var ioReader io.Reader
...
buff := bytes.NewBuffer([]byte{})
size, err := io.Copy(buff, ioReader)
if err != nil {
return err
}
reader := bytes.NewReader(buff.Bytes())
// Do something with `reader`
Run Code Online (Sandbox Code Playgroud)