Dave Cheney has written (yet another) excellent blog post on Go, on the 
subject of API design and caller-controlled allocations:

In this he compares two possible signatures for the io.Reader.Read method:
  func (r *Reader) Read(buf []byte) (int, error)
  func (r *Reader) Read() ([]byte, error)
and makes a very good case for why the first, albeit trickier to use, is 
the better API. The post also sets up a false dichotomy/straw man argument, 
comparing only two signatures when there are other alternatives too.

What about the following API:
  func (r *Reader) Read(buf []byte) (result []byte, err error)
If the buf argument is non-nil then buf is used to store the result, 
len(result) == the int returned by the actual Read(buf []byte) (int, error) 
If the buf argument is nil then a new []byte is created and returned, i.e. 
the allocation is done by Read and the method is as easy to use as Read() 
([]byte, error).
The semantics of the error return remain the same (i.e. Read might return 
both some bytes read and an error), but that is orthogonal to the memory 
An example of this pattern is here 

Given that slices are small and cheap to copy (a pointer to the data, a 
length, and a capacity) what are the downsides to using
  func (r *Reader) Read(buf []byte) (result []byte, err error)
as a method?

I am not suggesting that we change io.Reader (that would break 
everything!), just looking for input into good Go API design.

This would be a comment on Dave's fantastic blog, but the blog does not 
have comment functionality, so I'm asking here, and I know that Dave lurks 
here too.


You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 

Reply via email to