I define a struct, lets call it S. Just by doing that, I have created an infinite data types: S, pointer to S, pointer to pointer to S, etc
Out of this infinite serie of data types, only one of them has a default String() function already implemented, and that is S. <- is this true ? (1)
Because S already has a default String() method, if I define a String() method for *S (pointer to S type), this will have the disadvantage that it works when called for a *S but it will not get called for S (without pointer). When calling it for S (regular type, no pointer) the default String() method still gets invoked. <- is this true ?
That is why, when creating a custom String() function it is beneficial that its receiver is type S not pointer to S. Because *S has no default String() function, when calling String() on a pointer receiver, my custom String() (defined for S without pointer) is invoked. <- is this true ?
For the type **S (pointer of pointer of S), my custom String() function written for S, does not get involved. <- why is this, it contradicts statement (1)
No. String functions are not automatically implemented. The âprint familyâ of functions have default handling of builtin types, and then type assertion checks to see if the type implements fmt.Formatter, fmt.GoStringer or fmt.Stringer, and ultimately falls back to building a representation with the reflect package if the type doesnât define one.
You can call a (*T).String function on a variable or variable of type T; the compiler implicitly takes the address of the variable (or struct field, array/slice element, etc.) and uses that: Go Playground - The Go Programming Language However that doesnât happen if the value is boxed into an interface, such as when the value is passed into any of the âprint familyâ of functions.
Beneficial is a really subjective term, but I agree with you here
I donât know why this is, but Go doesnât allow methods to be defined on double-pointers, even if the pointers are defined types: Go Playground - The Go Programming Language, so thereâs no implicit call to T.String from a (**T).String.