首页 文章

为什么接口在没有直接访问的情况下不实现带指针引用的方法?

提问于
浏览
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:不能在interfaceModify的参数中使用u(类型用户)作为类型修饰符:用户不实现修饰符(修改方法有指针接收器)

这被解释为:

[...]方法调用获取指针没有用处 . 即使在编译器可以将值的地址传递给方法的情况下,如果方法修改了值,则更改将在调用者中丢失 .

但是,用 u.modify() 这样的直接调用替换 interfaceModify(u) 确实有效:编译器获取 u 的地址,并在Println()确认时修改其name属性 .

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

2 回答

  • 2

    我想你已经明白了 . 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)
    }
    
  • 4

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

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

    playground

相关问题