问题描述
我确实了解接口不会按照Go规范和FAQ来实现带有指针引用的方法,因为T和* T具有不同的方法集( https://golang.org/doc/faq#guarantee_satisfies_interface ).
I do understand that interface don't implement method with pointer reference as per Go spec and FAQ, as T and *T have different method sets (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)
}
并返回:
解释为:
即使在编译器可以将值的地址传递给方法的情况下,如果方法修改了该值,更改也将在调用方中丢失.
Even in cases where the compiler could take the address of a value to pass to the method, if the method modifies the value the changes will be lost in the caller.
但是,用像 u.modify()
这样的直接调用替换 interfaceModify(u)
确实可行:编译器采用 u ,并在Println()确认后修改其name属性.
However, replacing interfaceModify(u)
with a direct call like u.modify()
does work: the compiler takes the address of u, and will modify its name property as Println() confirms.
因此,我们能够在那种精确的情况下执行该操作,但不能在界面之一中执行该操作.我对此差异的唯一解释是,在 interfaceModify(m修饰符)
中,我们将直接将 u 复制到 m 使 m 在调用 modify()
时与相应地址匹配.因此,声明 u:=& user {默认名称"}
将因此将指针(即地址) u 复制到 m ,这就是为什么可以使用 m.modify()
的原因.我说得对吗?
So, we are able to do that operation in that precise case, but not in the interface one. My only explanation of that difference is that in interfaceModify(m modifier)
, we will have a direct copy of u to m, and no way for m to match corresponding address when calling modify()
.And, so, declaring u := &user{"Default Name"}
would thus copy the pointer (so address) u to m, and that's why m.modify()
is possible.Am I correct?
推荐答案
我认为您已经掌握了. u.modify()
之所以有效,是因为go认为它是(& u).modify()
的简写. interfaceModify(& u)
也将起作用.这是一个操场,其中有更多通过引用与价值传递的示例.
I think you've got it. u.modify()
works because go sees it as shorthand for (&u).modify()
. interfaceModify(&u)
would also work. Here's a playground with some more examples of pass by reference vs. value.
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)
}
这篇关于为什么在仍然可以直接访问的情况下,接口不使用指针引用实现方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!