Home > Article > Backend Development > Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?
Understanding the Difference Between t and *t
In this code snippet, we have a type TT with a String method that implements the fmt.Stringer interface:
package main import "fmt" type TT struct { a int b float32 c string } func (t *TT) String() string { return fmt.Sprintf("%+v", *t) } func main() { tt := &TT{3, 4, "5"} fmt.Printf(tt.String()) }
This code works because the fmt package invokes the String method to get the string representation of the TT value.
However, when the String method is modified to take a non-pointer receiver:
func (t *TT) String() string { return fmt.Sprintf("%+v", t) }
it causes a dead loop. Let's explain why:
Calling fmt.Sprintf("% v", t) passes a *TT (pointer to TT) value to the fmt package. Since the TT.String method has a pointer receiver, the fmt package will not find this method in the method set of the *TT type.
Changing the receiver to a non-pointer type means that the fmt package will find the String method in the method set of TT. However, this leads to infinite recursion because the method being called is the same one that is being used to format the value.
To avoid this issue, a new type can be created using the type keyword, effectively separating the receiver type from the value being passed to the fmt package:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
This works because the new type created by the type keyword doesn't have any methods, so the fmt package won't try to invoke the String method on the new type.
The above is the detailed content of Why Does Changing a Method Receiver from Pointer to Non-Pointer Lead to a Dead Loop When Using `fmt.Sprintf`?. For more information, please follow other related articles on the PHP Chinese website!