作者回复: 没错,虽然是副本,但却是指针的副本,SetName又是指针方法。所以综合起来这种修改就生效了。
另外这类副本都是浅表复制。也没错。
作者回复: 这主要是因为 Dog 和 *Dog 的零值是完全不同的,前者是 Dog{} ,而后者是 nil 。
作者回复: 对的,对于指针方法来说是这样。
作者回复: 你可以参照Go语言规范中的说明:https://golang.google.cn/ref/spec#Comparison_operators,请注意下面这句:
A value x of non-interface type X and a value t of interface type T are comparable when values of type X are comparable and X implements T. They are equal if t's dynamic type is identical to X and t's dynamic value is equal to x.
作者回复: 方法签名严格来说不包含方法名。
作者回复: 这与方法有没有返回值没有关系啊。值方法还是指针方法应该是类型定义者考虑的事情。作为使用者,你可以先假定方法的定义是正确的(可以使程序正常工作)。
回到你最后的问题。你可以看源码,也可以用 reflect 包里的 API 进行探查(不过比较麻烦)。不过我觉得通常没必要这么做。
作者回复: 郝林回复:首先,你要明白在Dog里内嵌Animal意味着什么。这意味着Dog类型中包含了一个Animal类型的匿名字段。正是由于这个匿名字段,Dog类型就包含了实现Animal接口所需的所有方法,只不过你并没有为这个匿名字段赋值而已。但是这个字段就摆在那儿了,匿名字段Animal的方法照样会融入Dog的方法集合。这是一个不争的事实,所以类型判断的时候照样会返回true。实际上,单从方法集合融入的这个方面讲,这与Dog内嵌PetTag是一样的。
这样的嵌入方式是可以的。当你要做部件动态装配的时候可以这么做,不论是嵌入接口类型还是嵌入非接口类型。当然了,内嵌接口类型会更加灵活一些,因为你可以为这个匿名字段赋予不同的实现值。
作者回复: 需要改动值内部数据的时候必须使用指针方法。其他时候就要看接口实现、被嵌入要求等方面了。我觉得一般情况下用指针方法就好了。
作者回复: 更精确的说法是:除了接口类型以外的所有引用类型的值,只要它的实际值为nil,自然就等于nil。
多解释两句:对于这些类型,它们的值就是实际值。而接口类型的值与它们不同,会在实际值之外再包一层,正如文中所述。