snprintf() in Go with at most constant memory requirement difference than snprintf(3)?

88 views
Skip to first unread message

fge...@gmail.com

unread,
Feb 6, 2024, 4:52:29 AMFeb 6
to golang-nuts
C *nprintf(3) implementations stop the conversion when n is reached.
I couldn't find a similar functionality in the standard library, what
did I miss?
If there isn't any, any idea how to implement that without
reimplementing all format helpers?
thanks!

Brian Candler

unread,
Feb 6, 2024, 6:18:38 AMFeb 6
to golang-nuts
The C functions are mainly there to prevent overrunning already-allocated buffers, which isn't an issue with Go.

You could truncate the response:

    a := fmt.Sprintf("%s", "Blah blah blah")[0:10]

You could use suitable precision specifiers:

    a := fmt.Sprintf("%.10s", "Blah blah blah")

You could make a custom type which implements io.Writer and truncates at a given size, and pass it to fmt.Fprintf

fge...@gmail.com

unread,
Feb 6, 2024, 6:51:16 AMFeb 6
to Brian Candler, golang-nuts
On Tue, Feb 6, 2024 at 12:18 PM 'Brian Candler' via golang-nuts
<golan...@googlegroups.com> wrote:
>
> The C functions are mainly there to prevent overrunning already-allocated buffers, which isn't an issue with Go.
Thanks! In addition to that, It also helps with code with upper limit
memory-requirement, which fmt.Sprintf() can't.
Though I can live with careful coding and not using Sprintf() in this
case, I just hoped possibly somebody else already thought about
needing that.

...
> You could make a custom type which implements io.Writer and truncates at a given size, and pass it to fmt.Fprintf
IIUC this sounds similar to what I'm asking for. How to use a limiting
io.Writer with fmt.Sprintf()? How would this limit fmt.Sprintf()'s
memory usage?

Brian Candler

unread,
Feb 6, 2024, 9:03:19 AMFeb 6
to golang-nuts
> Thanks! In addition to that, It also helps with code with upper limit
> memory-requirement, which fmt.Sprintf() can't.

If you're processing data from untrusted sources, then you probably ought to validate it first.

> How to use a limiting
> io.Writer with fmt.Sprintf()? How would this limit fmt.Sprintf()'s
> memory usage?

Proof-of-concept: https://go.dev/play/p/kJabvvTzFH0

I don't know under what circumstances this would cause Fprintf to terminate early; it depends on how much buffering it does internally. I would guess that a large single argument like "%s" would be treated as a single entity, and very likely allocate an intermediate buffer of the full size.

If this matters in your use case, then I think you shouldn't be using Sprintf and friends.

fge...@gmail.com

unread,
Feb 6, 2024, 11:02:11 AMFeb 6
to golang-nuts
(This time reply to list. Sorry Brian.)
I should probably limit memory usage outside of the process anyway.
A bit unexpected, though I'm not complaining.
cheers
Reply all
Reply to author
Forward
0 new messages