Description
What version of Go are you using (go version
)?
1.16
Does this issue reproduce with the latest release?
Sure.
What operating system and processor architecture are you using (go env
)?
N/A
What did you do?
Profiled something that was using Sprintf in a minor way.
What did you expect to see?
Less Sprintf in the profile.
What did you see instead?
So much Sprintf.
The issue here is that most of what's happening is WAY cheaper than allocations. strconv
has AppendInt, but that can't do formatting.
It makes sense, for most uses, that fmt.Sprintf
is an allocator that produces a string, but there are times when you want formatted-output, but want to write into a []byte. And you can do that with bytes.Buffer
and fmt.Fprintf
, but creating a bytes.Buffer around a []byte
is... an allocation. And fmt.Fprintf does an allocation. (Curiously, if I do fmt.Fprintf
into a bytes.Buffer I just made for that purpose, I only get the one allocation.)
What I want: Something like Sprintf
, but that can write into a []byte, and can fail gracefully if there's not enough space to write things.
Proposed name: fmt.Snprintf
, because snprintf
is what you call when you already have a buffer you want written to and you have a length limit in mind.
So, fmt.Snprintf(dest []byte, fmt string, args ...interface{}) (int, error)
, perhaps. The C standard's answer to "what if n isn't big enough" is "you report the n you would have used if n had been big enough", which exists to allow a single-pass process to figure out how much space you actually need. Alternatively, it could return number of bytes actually written, and if it didn't fit, an error with a concrete type that indicates space needed.
I note, browsing source, that fmt already has fmtBytes
, although this doesn't do quite the thing this would need.