Вы реализовали интерфейс для типа "указатель на IPAddr", а распечатываете тип "IPAddr".
С этим возникает сложность из-за двойных стандартнов, принятых в Go, хотя и логичных. Запомните навсегда:
Pointer type can access the methods of its associated value type, but not vice versa. That is, a *Dog value can utilize the Speak method defined on Dog, but as we saw earlier, a Cat value cannot access the Speak method defined on *Cat.
То есть в вашем случае всё бы работало и при правильном совпадении типов
И при неправильной, противоположной вашему коду ситуации - если бы вы реализовали интерфейс для самого типа, а пытались распечатать указатель на него.
Объясняется это просто - если метод реализован для указателя, он, скорее всего, может что-то менять в объекте по этому указателю, поэтому передавая объект по значению, а не по указателю - он бы менял не в самом объекте, а в его копии, которая бы делалась при передачи по значению. Это явно не то, чего ожидал писатель метода.
В обратном же случае, если метод определён для типа по значению, а не по указателю, очевидно что метод ничего в самом значении не меняет (если бы попытался, то менял бы опять же в копии значения). А раз он там ничего не меняет, можно смело передать наш объект под ссылкой.
Тут объясняется всё подробно:
https://github.com/golang/go/wiki/MethodSets