英文:
Why can methods in Go only be declared on types defined in the same package?
问题
Go Tour中提到:
你只能声明一个接收者类型与方法所在包相同的方法。你不能声明一个接收者类型与方法所在包不同的方法(包括内置类型如int)。
除了避免每个人都基于int
和string
构建自己的方法之外,还有其他原因吗?我在Google上搜索了一下,但找不到任何相关的信息。
英文:
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.
答案1
得分: 10
原因是,如果你可以在其他包的类型上定义方法,那么你就可以修改其他包的行为。这是因为给定类型的方法集可以影响该类型的值的使用方式。
例如,考虑fmt.Println
函数。当你将参数传递给fmt.Println
时,它会根据一组规则打印该值的字符串表示形式。其中一个规则是,如果该值的类型具有String() string
方法(即实现了fmt.Stringer
接口),那么将调用该方法以获取该值的字符串表示形式。
因此,假设我们有一个名为foo
的包,该包定义了一个名为FooInt
的类型,如下所示:
type FooInt int
现在假设该包还有一个名为PrintFooInt
的函数:
func PrintFooInt(f FooInt) { fmt.Println(f) }
这将打印f
的整数值。但是假设你(在另一个包中,比如main
)能够为FooInt
添加方法。那么你可以这样做:
func (f FooInt) String() string { return "foobar!" }
这实际上会改变foo.PrintFooInt
的行为,而这在包的外部是不应该可能的。
英文:
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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论