Default String() function - question

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)

Help me figure out the truth, hopefully this truth will set me free of my doubts :slight_smile:
also look at t his example

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.

I’m not sure how to answer this. You cannot define a String method on both a T and a *T:

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: 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 :slight_smile:

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:, so there’s no implicit call to T.String from a (**T).String.