我确实理解接口没有按照 Go 规范和 FAQ 实现带有指针引用的方法,因为 T 和 *T 有不同的方法集(https://golang.org/doc/faq#guarantee_satisfies_interface https://golang.org/doc/faq#guarantee_satisfies_interface).
所以,这是行不通的:
package main
import (
"fmt"
)
type user struct {
name string
}
type modifier interface {
modify()
}
func (u *user) modify() {
u.name = "My name"
}
func interfaceModify(m modifier) {
m.modify()
}
func main() {
u := user{"Default Name"}
interfaceModify(u)
fmt.Println(u.name)
}
并返回:
./main.go:26: 不能在接口修改参数中使用 u (类型 user)作为类型修饰符:用户没有实现修饰符(修改方法有指针接收器)
这解释为:
[...]方法调用没有有用的方法来获取指针。
即使编译器可以将值的地址传递给方法,如果方法修改了值,则调用者中的更改也会丢失。
然而,更换interfaceModify(u)
直接调用,例如u.modify()
确实有效:编译器获取地址u,并将按照 Println() 确认修改其 name 属性。
因此,我们能够在这种精确的情况下执行该操作,但不能在界面中执行该操作。我对这种差异的唯一解释是interfaceModify(m modifier)
,我们将有一个直接副本u to m,并且没有办法m调用时匹配对应的地址modify()
。
并且,所以,宣布u := &user{"Default Name"}
因此会复制指针(所以地址)u to m,这就是为什么m.modify()
是可能的。
我对么?
我想你已经明白了。u.modify()
有效,因为 go 将其视为简写(&u).modify()
. interfaceModify(&u)
也会起作用。这是一个游乐场,其中包含更多按引用传递与按值传递的示例。
https://play.golang.org/p/HCMtcFAhLe https://play.golang.org/p/HCMtcFAhLe
package main
import (
"fmt"
)
type user struct {
name string
}
type userPointer struct {
user
}
func (up *userPointer) modify() {
up.name = "My name"
}
type modifier interface {
modify()
}
func (u user) modify() {
u.name = "My name"
}
func interfaceModify(m modifier) {
m.modify()
}
func main() {
u := user{"Default Name"}
u.modify()
fmt.Println(u.name)
interfaceModify(u)
fmt.Println(u.name)
up := userPointer{user{"Default Name"}}
interfaceModify(&up)
fmt.Println(up.name)
// short hand version
up.name = "Default Name"
up.modify()
fmt.Println(up.name)
// long hand version https://golang.org/ref/spec#Calls
up.name = "Default Name"
(&up).modify()
fmt.Println(up.name)
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)