Too Much Go Misdirection

https://news.ycombinator.com/rss Hits: 19
Summary

Poking through layers of indirection in go trying to recover some efficiency.Many functions in go take an io.Reader interface as input. This is a sensible default, allowing for streaming of data, instead of loading the entirety into memory. In some cases, though, we need the bytes. Which we may already have, in which case it would be great to simply use those bytes. Alas, this can be quite difficult.contextI’m decoding some images. I’m using libavif and libheif via C bindings. For reasons primarily motivated by simplicity, I’m using the simple memory interfaces for these libraries, which makes it much easier to get the data from go into C. The streaming interface is much more work, and anyway the libraries would then just buffer the data internally, making another copy. Not every decoder fully works in a streaming fashion.So the primary do the work function takes a []byte and passes it to C, and there’s a wrapper that does things the go way with an io.Reader, which does a full read into a temporary buffer before sending it along. Now, as it happens, my application also uses []byte internally because that’s what I’m getting out of libsqlite3 (because again, the streaming interface is much trickier to wire up) and also because that’s what you get when doing RPC with encoding/gob. I think this is not an unusual scenario.bytesWhat I would like is for my image decoding function to notice that the io.Reader it has been given is in fact a bytes.Reader so we can skip the copy. Anyone who’s spent any time looking around in the go standard library has noticed that similar shortcuts are commonplace. Interfaces are type checked against specific implementations, and then optimized code paths are taken. Well, we can do the check, but it doesn’t immediately help, because bytes.Reader doesn’t expose its internal byte slice.But it’s in there somewhere and I will not be denied. if br, ok := r.(*bytes.Reader); ok { data = *(*[]byte)(unsafe.Pointer(br)) } else { var buf bytes.Buffer io...

First seen: 2025-05-19 16:55

Last seen: 2025-05-20 10:10