When you call a method with a receiver of a pointer to a variable ( s in your example), then the address of this value will be taken automatically. So you basically call (&s).toupper() . This mechanism works for all addressable values.
The return values โโof functions are not addressed unless you store them in a variable (so that they have a constant place in the current stack stack or heap).
I would recommend the following API because it looks like the user of your string type should work with String , not *String . Therefore, it makes sense to develop a consistent API that also uses String to avoid confusion. Passing a string by value is extremely large because they are implemented as pointers to immutable arrays inside:
func (s String) tolower() String { return String(strings.ToLower(string(s))) }
This method does not need a pointer receiver, because it does not change the current line. Instead, it returns a new line. You can also easily link these methods.
Alternatively, you can implement the methods as follows:
func (s *String) tolower() *String { *s = String(strings.ToLower(string(*s))) return s }
In this case, you continue to return the same pointer. Thus, to call (s.tolower()).toupper() you need to have the address s , which is possible since you assigned it to a variable. Then further calls to methods in the chain are possible, because you call them with a pointer to your initial variable. This is different from your attempt at a method chain, each method call had to take the address of a temporary variable in order to change it (which is not very useful).
source share