I tried to implement the Stringer interface on my type as follow:
package main
import (
"fmt"
)
type IPAddr [4]byte
// TODO: Add a "String() string" method to IPAddr.
func (o IPAddr) String() string {
return fmt.Sprintf("%v.%v.%v.%v", o[0], o[1], o[2], o[3])
}
func main() {
hosts := map[string]IPAddr{
"loopback": {127, 0, 0, 1},
"googleDNS": {8, 8, 8, 8},
}
for name, ip := range hosts {
fmt.Printf("%v: %v\n", name, ip)
fmt.Printf("%v\n", ip.String())
}
}
In the code above, I used a value receiver to implement the String() method. The Printf recognised my implementation and called the correct String function on my type.
Output:
googleDNS: 8.8.8.8
8.8.8.8
loopback: 127.0.0.1
127.0.0.1
Then I updated my code to use pointer receiver:
func (o *IPAddr) String() string {
return fmt.Sprintf("%v.%v.%v.%v", o[0], o[1], o[2], o[3])
}
The output of the updated code:
loopback: [127 0 0 1]
127.0.0.1
googleDNS: [8 8 8 8]
8.8.8.8
The Printf method didn't call my String method anymore. The output told me that Printf use the default String method of the type. However, when I called ip.String(), my method was used.
Can someone explain to me this behaviour, please? As far as I know, we can implement methods of interfaces by both value and pointer receivers.
Thank you.