The Go Tour says the following:
You can only declare a method with a receiver whose type is defined in the same package as the method. You cannot declare a method with a receiver whose type is defined in another package (which includes the built-in types such as int).
Is there a reason for this other than avoiding everyone building their own methods off int
and string
? I've Googled around, but can't find anything referencing it.
The reason is that if you could define methods on other packages' types, you could modify the behavior of other packages. This is because the method set of a given type can have an effect on how values of that type are used.
Consider, for example, the fmt.Println
function. When you pass an argument to fmt.Println
, it will print a string representation of that value based on a set of rules. One of those rules is that if the type of the value has a String() string
method (that is, it implements the fmt.Stringer
interface), then that method will be called in order to obtain the string representation of the value.
Thus, imagine that we have a package, foo
, and that package has a type, FooInt
, defined as follows:
type FooInt int
Now imagine that this package also has a function, PrintFooInt
:
func PrintFooInt(f FooInt) { fmt.Println(f) }
This will print the integer value of f
. But let's say that you (in a different package, say main
) were able to add methods to FooInt
. Then you could do this:
func (f FooInt) String() string { return "foobar!" }
This would actually change the behavior of foo.PrintFooInt
, which shouldn't be possible from outside the package.