为什么界面不能实现带指针引用的方法,同时仍然可以直接访问?

时间:2016-11-27 11:00:12

标签: go

我知道界面没有按照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)
}

并返回:

  

./ main.go:26:不能在interfaceModify的参数中使用u(类型用户)作为类型修饰符:     用户没有实现修饰符(修改方法有指针接收器)

这解释为:

  

[...]方法调用获取指针没有用处。

     

即使编译器可以将值的地址传递给方法,如果方法修改了值,则更改将在调用者中丢失。

但是,使用interfaceModify(u)之类的直接调用替换u.modify()确实有效:编译器获取 u 的地址,并将修改其name属性,因为Println()已确认

因此,我们能够在这种精确的情况下进行该操作,但不能在界面中进行。我对这种差异的唯一解释是,在interfaceModify(m modifier)中,我们会直接将 u 复制到 m ,而 m 在调用modify()时匹配相应的地址。 因此,声明u := &user{"Default Name"}会将指针(因此地址) u 复制到 m ,这就是为什么m.modify()是可能。 我是对的吗?

2 个答案:

答案 0 :(得分:4)

我想你已经明白了。 u.modify()有效,因为go将其视为(&u).modify()的简写。 interfaceModify(&u)也可以。这是一个游乐场,里面有一些参考文献和价值传递的例子。

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)
}

答案 1 :(得分:2)

T类型不是'& T'类型。换句话说,struct的类型指针不是结构类型。因此,如果您决定使用指针接收器实现一个方法,则必须使用指针而不是结构本身,因为确切的指针实现了该方法。你的代码只缺少一个字符。

interfaceModify(u)更改为interfaceModify(&u)

playground