Go String(): Difference between revisions
Line 48: | Line 48: | ||
=The <tt>fmt.Stringer</tt> Interface= | =The <tt>fmt.Stringer</tt> Interface= | ||
The <code>fmt.Stringer</ | The <code>fmt.Stringer</code> interface declares <code>String() string</code> as its only method: | ||
<syntaxhighlight lang='go'> | <syntaxhighlight lang='go'> |
Revision as of 01:20, 31 August 2024
Internal
Overview
Java developers are used to declare a public String toString() {...}
method in their class to get instances of that class rendered as custom Strings. Go has a similar facility, the String() string
method.
The default format of values of a custom type can be controlled by defining a method:
func String() string
and associating it with the type, by declaring the type as the method's receiver. It is said that the method defines the "native" format for that type.
The String()
method's intention is to read the receiver's state and render it, never to modify it. In consequence, the String()
should declare a value receiver.
func (t SomeType) String() string {
return fmt.Stringf("...", "...")
}
Thanks to compiler's facilities, String()
can be invoked with both values and pointers:
type SomeType struct {
s string
}
func (s SomeType) String() string {
return "<" + s.s + ">"
}
...
t := SomeType{s: "A"}
fmt.Printf("%v\n", t) // prints <A>
fmt.Printf("%v\n", &t) // prints <A>
fmt.Printf("%s\n", t) // prints <A>
fmt.Printf("%s\n", &t) // prints <A>
Since we use a value receiver, the implementation does not have to protect against the receiver being nil
.
fmt
package printing functions automatically invoke the String()
method, if defined, on instances of the type when the "%s" and "%v" conversion characters are used.
The fmt.Stringer Interface
The fmt.Stringer
interface declares String() string
as its only method:
type Stringer interface {
String() string
}
fmt.Stringer
is implemented by any type that has a String() string
method, The String()
method is used to print values passed as an operand to any format that accepts a string or to an unformatted printer such as Print
.
Note that is important whether we declare a value or a pointer receiver type. Depending on how the receiver type is declared, we will have to pass to the rendering code either a value, or a pointer to the instance of the type to achieve the desired behavior.
Example
type SomeType struct {
ID string
}
// String makes SomeType implement the fmt.Stringer interface. It is important whether a value or a pointer receiver type is declared.
func (e SomeType) String() string {
return fmt.Sprintf("SomeType[%s]", e.ID)
}
...
t := SomeType{ID: "001"}
fmt.Println(t)
will render:
SomeType[001]