我确实了解接口(interface)不会按照Go spec和FAQ来实现带有指针引用的方法,因为T和* T具有不同的方法集(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)
}
并返回:
解释为:
但是,用像
interfaceModify(u)
这样的直接调用替换u.modify()
确实可以:编译器采用 u 的地址,并在Println()确认时修改其name属性。因此,我们能够在那种精确的情况下执行该操作,但不能在接口(interface)之一中执行该操作。我对此差异的唯一解释是,在
interfaceModify(m modifier)
中,我们将 u 直接复制到 m ,而在调用modify()
时, m 无法匹配相应的地址。因此,声明
u := &user{"Default Name"}
会因此将 u 指针(so地址)复制到 m 中,这就是m.modify()
可行的原因。我对么?
最佳答案
我想你已经明白了。 u.modify()
之所以有效,是因为go将其视为(&u).modify()
的简写。 interfaceModify(&u)
也可以。这是一个操场,其中有更多通过引用与值(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)
}