The Stringer Interface
func (t Type) String() string {
return "text"
}
Implementing Stringer
The standard library's fmt.Stringer interface requires exactly one method, String() string. Any type that implements it gets used automatically whenever it's printed with Println, Printf's %v, or similar.
Example: Implementing Stringer
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
// Define a struct type named Point
type Point struct {
X, Y int
}
// Define the method String on type Point
func (p Point) String() string {
// Sprintf builds a formatted string instead of printing it
return fmt.Sprintf("(%d, %d)", p.X, p.Y)
}
// main is where the program starts running
func main() {
// Short declaration: create p and infer the type
p := Point{3, 4}
// Print the values followed by a newline
fmt.Println(p)
}
Login to try C/C++/Java/PHP code in the editor
Without vs With Stringer
A struct without a String() method prints its default, somewhat verbose field-by-field representation, while implementing Stringer gives you full control over exactly how it reads when printed.
Example: Without vs With Stringer
// Every Go file belongs to a package; main builds an executable
package main
// Import the fmt package
import "fmt"
type Status int
const (
Active Status = iota
Inactive
)
// Define the method String on type Status
func (s Status) String() string {
// Check whether s == Active
if s == Active {
// Send "Active" back to the caller
return "Active"
}
// Send "Inactive" back to the caller
return "Inactive"
}
// main is where the program starts running
func main() {
// Print the values followed by a newline
fmt.Println(Active)
fmt.Println(Inactive)
}
Login to try C/C++/Java/PHP code in the editor
Avoiding Infinite Recursion
A common mistake is calling fmt.Sprintf("%v", p) on the receiver p inside its own String() method -- since %v triggers String() again, this recurses forever. Building the string from individual fields avoids the problem.
Example: Avoiding Infinite Recursion
package main
import "fmt"
type Temp struct {
Celsius float64
}
func (t Temp) String() string {
return fmt.Sprintf("%.1f°C", t.Celsius) // uses the field, not t itself
}
func main() {
fmt.Println(Temp{Celsius: 21.5})
}
Login to try C/C++/Java/PHP code in the editor
- Naming the method something other than exactly 'String() string' -- fmt only recognizes that exact signature for the Stringer interface.
- Accidentally causing infinite recursion by calling fmt.Sprintf("%v", t) on the receiver itself inside its own String() method.
- Forgetting that a String() method defined with a pointer receiver only applies when printing a pointer to the type, not the value itself.
- The fmt.Stringer interface requires one method: String() string.
- Implementing it lets fmt.Println and %v automatically use your custom, readable representation.
- Calling fmt formatting functions on the receiver itself inside String() causes infinite recursion -- format the underlying fields instead.
- Stringer is a great example of Go's small, implicit interfaces in everyday use.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: