如何定义接收指针的Go接口方法的实现?

时间:2017-04-25 04:50:45

标签: pointers go interface

以下程序运行良好。

package main

import (
    "fmt"
)

type Person interface {
    Hello()
}

type Joker struct {
    Name string
}

func (j Joker) Hello() {
    fmt.Println(j.Name, "says, \"Hello!\"")
}

func main() {
    var j Joker = Joker{"Peter"}
    invokeHello(j)
}

func invokeHello(p Person) {
    p.Hello()
}

这是输出。

$ go run foo.go
Peter says, "Hello!"

但是当我更改Hello方法以接收指针时,我会收到错误。

package main

import (
    "fmt"
)

type Person interface {
    Hello()
}

type Joker struct {
    Name string
}

func (j *Joker) Hello() {
    fmt.Println(j.Name, "says, \"Hello!\"")
}

func main() {
    var j *Joker = &Joker{"Peter"}
    invokeHello(j)
}

func invokeHello(p *Person) {
    p.Hello()
}

以下是错误。

$ go run bar.go
# command-line-arguments
./bar.go:21: cannot use j (type *Joker) as type *Person in argument to invokeHello:
    *Person is pointer to interface, not interface
./bar.go:25: p.Hello undefined (type *Person has no field or method Hello)

如何修复第二个程序?

2 个答案:

答案 0 :(得分:3)

func invokeHello(p *Person) {
    p.Hello()
}

p*Person类型,*Joker实现接口Person,将invokeHello还原为:

func invokeHello(p Person) {
    p.Hello()
}

这将修复第二个程序。

我认为你对golang interface type

有误导
  

接口类型指定称为其接口的方法集。接口类型的变量可以使用方法集存储任何类型的值,该方法集是接口的任何超集。据说这种类型实现了界面。

答案 1 :(得分:0)

修复

您无法使用指向interface类型的指针。 这就是问题:

func invokeHello(p *Person) {
    p.Hello()
}

应该是:

func invokeHello(p Person) {
    p.Hello()
}

接口实现

类型实现接口。如果type具有适合于接口中声明的方法的方法,则该接口由该类型实现。

  

Go中的接口提供了一种指定对象行为的方法:如果有什么可以做到这一点,那么可以在这里使用它。

类型与类型指针

Type*Type是不同的类型。例如,*Type可以实现接口,但Type无法实现它。但*InterfaceType确实无法使用。

如果要接收指向期望接口类型的函数中的类型的指针,请使用指针接收器实现接口,就像在第二个示例中所做的那样。

Example

type Person interface {
    Hello()
}

type Joker struct {
    Name string
}

/*
A Hello method declared with a pointer receiver which means that a pointer to
the Joker type (*Joker) not Joker type itself implements Person interface.
*/
func (j *Joker) Hello() {
    fmt.Println(j.Name, "says, \"Hello!\"")
}

/*
invokeHello receives ANY type which statisfies Person interface.
In this case this is pointer to Joker type.
*/
func invokeHello(p Person) {
    p.Hello()
}

func main() {
    i := Joker{"Peter"}
    j := &i
    // Note difference between types
    fmt.Printf(
        "Joker type: %s\nPointer to Joker type: %s\n",
        reflect.TypeOf(i), reflect.TypeOf(j))
    invokeHello(j)
}

否则,如果您想要接收类型的值,请使用值接收器实现接口,就像您在第一个示例中所做的那样。