为什么在仍然可以直接访问的情况下,接口不使用指针引用实现方法? [英] Why interface don't implement method with pointer reference while direct access is still possible?

查看:58
本文介绍了为什么在仍然可以直接访问的情况下,接口不使用指针引用实现方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我确实了解接口不会按照Go规范和FAQ来实现带有指针引用的方法,因为T和* T具有不同的方法集(

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

并返回:

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

./main.go:26: cannot use u (type user) as type modifier in argument to interfaceModify: user does not implement modifier (modify method has pointer receiver)

解释为:

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

[…]there is no useful way for a method call to obtain a pointer.

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

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

这篇关于为什么在仍然可以直接访问的情况下,接口不使用指针引用实现方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆