stack overflow on Sprintf []byte

1,233 views
Skip to first unread message

bsr

unread,
Nov 13, 2015, 12:47:37 PM11/13/15
to golang-nuts
Hi,

The following program gives "stack overflow" if I try to print without casting to` []byte`. Is this a bug? (it says process took too long
Program exited. now)

runtime: goroutine stack exceeds 250000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x183cb0, 0xe)
	/usr/local/go/src/runtime/panic.go:527 +0x100
runtime.newstack()
	/usr/local/go/src/runtime/stack1.go:794 +0x1000


so 

//return fmt.Sprintf("%x", e)  --> gives error
return fmt.Sprintf("%x", []byte(e)) --> works



//-------- pgm -------------
package main

import (
"encoding/hex"
"fmt"
)

type id []byte

func (e id) String() string {
return fmt.Sprintf("%x", e)
// return fmt.Sprintf("%x", []byte(e)) //Works fine
}

func main() {
s, err := hex.DecodeString("9a578a536c")
if err != nil {
panic(err)
}
e := id(s)
fmt.Println("key:", s, e.String())
}

Ian Lance Taylor

unread,
Nov 13, 2015, 12:54:08 PM11/13/15
to bsr, golang-nuts
On Fri, Nov 13, 2015 at 9:47 AM, bsr <bsr...@gmail.com> wrote:
>
> The following program gives "stack overflow" if I try to print without
> casting to` []byte`. Is this a bug? (it says process took too long
> Program exited. now)

Quoting from https://golang.org/pkg/fmt:

To avoid recursion in cases such as

type X string
func (x X) String() string { return Sprintf("<%s>", x) }
convert the value before recurring:

func (x X) String() string { return Sprintf("<%s>", string(x)) }

Jakob Borg

unread,
Nov 13, 2015, 3:20:20 PM11/13/15
to Ian Lance Taylor, bsr, golang-nuts
I have to admit I'm a bit surprised in this case though. I'd have
expected %s, %v and maybe %q to call the String() method, but not %x.
But in fact %x returns the hexadecimal encoding of the result of
String()... I'm guessing this is because the "id" type doesn't match
anything else fmt.Sprintf is looking for, other than the stringer
interface, and it doesn't realize it's underlying bytesliceness?

//jb

Matt Harden

unread,
Nov 13, 2015, 4:01:13 PM11/13/15
to Jakob Borg, Ian Lance Taylor, bsr, golang-nuts

Except when printed using the verbs %T and %p, special formatting considerations apply for operands that implement certain interfaces. In order of application:

1. If the operand is a reflect.Value, the concrete value it holds is printed as if it was the operand.

2. If an operand implements the Formatter interface, it will be invoked. Formatter provides fine control of formatting.

3. If the %v verb is used with the # flag (%#v) and the operand implements the GoStringer interface, that will be invoked.

If the format (which is implicitly %v for Println etc.) is valid for a string (%s %q %v %x %X), the following two rules apply:

4. If an operand implements the error interface, the Error method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

5. If an operand implements method String() string, that method will be invoked to convert the object to a string, which will then be formatted as required by the verb (if any).

Your type doesn't match any of 1-4 above, but it does match 5, so it uses that before falling back on the special handling for []byte.
Here's an example with a type that doesn't implement String(): https://play.golang.org/p/ufkC5XqzPM

--
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...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
Reply all
Reply to author
Forward
0 new messages