This is one part of Go I'm having trouble understanding. A buffer is an ordered collection of bytes. Some functions read data into buffers, or out of buffers, and I can make a new buffer out of a []byte.
One new thing is that a buffer stores a marker of the 'current position', and has a Next
method that reads n bytes from the marker while advancing it. Okay. And they have a ReadFrom
which reads from a data source until it indicates EOF, and stores it in the buffer.
Is that essentially all it is? Is Buffer
a struct that stores a slice/array of bytes and a current-position marker, with a few methods added? Is the purpose of a buffer to represent some data I might read or write in chunks rather than all at once?
I'd welcome any advice/explanations. I bought a book on Go and devoured it, and I'm enjoying learning the language, the core language features all clicked for me on day one, but the stdlib is giving me some trouble with things like this.
评论:
earthboundkid:
verisimilarity:Use the source, Luke: https://golang.org/src/bytes/buffer.go#L17
rimpy13:Yes, a Buffer is just what you said: a struct that contains a byte slice (probably) and metadata. It also gives useful functions for buffer operations, like you said.
It's nothing super special; it's just a nice abstraction built without any fancy new language features like you'd find in less elegant languages for less civilized ages ;)
ask:Buffer is a high level idea.
One way to implement one is to use a byte array/slice as the data container.
Your question is similar to asking “what separates a vehicle from a motorcycle?”
hobbified:Fancy arrays, just like integers are just fancy bits (etc). :-)
earthboundkid:Because Buffer has Read, Write, ReadFrom, and WriteTo methods, it implements several of the useful io interfaces (Reader, Writer, ReadWriter, ReaderFrom, WriterTo), which means that you can use it with all kinds of core and non-core functions that deal with those interfaces. If you wrap it with ioutil.NopCloser it can also do Closer, ReadCloser, WriteCloser, and ReadWriteCloser. It's "just" a type to adapt a
[]byte
to all of those interfaces so that you can use it in places you would otherwise use a file or socket. Although if you look at the source as /u/earthboundkid suggests you'll see that it's not exactly trivial.There's also bytes.Reader, which is similar except for two things:
- It doesn't have any of the writing methods, and won't modify the underlying
[]byte
(and, of course, doesn't do Writer, ReadWriter, or ReaderFrom).- It does have Seek and ReadAt methods, which means that it additionally works as a Seeker, ReadSeeker, and ReaderAt.
In theory there's no reason why there couldn't be a single type that combined the features of both and acted as a ReadWriteSeeker, but the Go maintainers have never given a shit for orthogonality, and doing that would complicate the implementation, so we don't get that one :)
hobbified:How would a Buffer with Seek work? In a normal Buffer, reads are one time only, so it would be pretty different if you could seek too.
earthboundkid:Like a file rather than like a pipe. Reading moves the pointer but doesn't drop the data. Which, yeah, is another reason you wouldn't want to use it most of the time.
djherbis:That would be a nice type to have. Bytes.Buffer returns the backing slice, so if you give that to bytes.Reader, it won’t allocate. That will let you seek but not write. A new type for seek writing might be nice too.
dilap:My lib djherbis/buffer has a type called BufferAt which implements io.ReaderAt/io.WriterAt so you can read/write from/to different places in the buffer.
You can get a BufferAt using buffer.New which is backed by bytes.Buffer.
So Go helpfully has the nice, simple interfaces io.Reader and io.Writer, for anything that can be read from or written to.
bytes.Buffer is simply the answer to the question, "how would I implement these interfaces writing and writing to and from a byte-slice?"
