Home > Article > Backend Development > Why Does Using a Pointer Receiver for `String()` Method Prevent a Dead Loop in Go String Formatting?
Understanding the Difference Between "t" and "*t" in Go String Formatting
In a Go program, variable names can be prefixed with an asterisk (*) to indicate a pointer type. This distinction is crucial in the context of string formatting using the fmt package.
Question:
Consider the following code:
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()) }
Why does the code work when String has a pointer receiver (func (t *TT) String() string), but causes a dead loop when the receiver is a non-pointer type (func (t TT) String() string)?
Answer:
The fmt package checks for the existence of the String() method in the operand it receives. When the receiver of String is a pointer type, the method set of the base type does not include String(), so the fmt package does not call it.
In contrast, when the receiver is a non-pointer type, String() is included in the method set of the base type. This means the fmt package calls String(), which in this case, is the same method being invoked, leading to an infinite loop.
Prevention:
To avoid this endless loop, consider creating a new type using the type keyword and applying type conversion to the value being formatted:
func (t TT) String() string { type TT2 TT return fmt.Sprintf("%+v", TT2(t)) }
This approach prevents the indirect recursion by isolating the String() method within the new type created by the type keyword.
The above is the detailed content of Why Does Using a Pointer Receiver for `String()` Method Prevent a Dead Loop in Go String Formatting?. For more information, please follow other related articles on the PHP Chinese website!