2016-11-27 96 views
1

我明白接口不按照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:不能使用u(用户类型)的类型修饰符在争论interfaceModify : 用户不实现改性剂(修改方法具有指针接收器)

此作为说明:

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

即使在编译器可以将值的地址传递给方法的情况下,如果该方法修改该值,那么更改将在调用者中丢失。

然而,像u.modify()直接调用替换interfaceModify(u)做工作:编译器会的ü地址,并修改其名称属性为的println()确认。

因此,我们能够在那种精确的情况下做到这一点,而不是在界面之一。我的这种差异的唯一解释是,在interfaceModify(m modifier),我们将有ü直接拷贝到,并没有办法调用modify()时要匹配相应的地址。 并且,因此,宣布从而u := &user{"Default Name"}将复制的指针(这样的地址)ü,这就是为什么m.modify()是可能的。 我正确吗?

回答

4

我想你已经明白了。 u.modify()的作品,因为去看它作为(&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) 
} 
2

T类型不是 '& T' 类型。换句话说,指向结构体的类型指针不是结构体类型。所以如果你决定实现一个带有指针接收器的方法,你必须使用指针而不是结构本身,因为指针实现了方法。你的代码只有一个字符。

变化interfaceModify(u)interfaceModify(&u)

playground

相关问题