我确实了解接口(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)
}

10-07 23:58