Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/go/7.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Pointers 如何定义接收指针的Go接口方法的实现?_Pointers_Go_Interface - Fatal编程技术网

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

Pointers 如何定义接收指针的Go接口方法的实现?,pointers,go,interface,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"} inv

下面的程序运行良好

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)
如何修复第二个程序

func invokeHello(p *Person) {
    p.Hello()
}
p
是类型
*Person
*Joker
实现接口
Person
,还原
调用hello

func invokeHello(p Person) {
    p.Hello()
}
这将修复第二个程序

我想你对我有误解

接口类型指定称为其接口的方法集。接口类型的变量可以使用作为接口的任何超集的方法集存储任何类型的值。这种类型被称为实现接口

修理 您不能使用指向
接口
类型的指针。
这就是问题所在:

func invokeHello(p *Person) {
    p.Hello()
}
应该是:

func invokeHello(p Person) {
    p.Hello()
}
接口实现 类型实现接口。如果类型具有适合于接口中声明的方法的方法,则接口由该类型实现

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

类型与指向类型的指针
类型
*类型
是不同的类型。例如,
*Type
可以实现一个接口,但是
Type
不能实现它。但是,
*接口类型
确实没有使用的意义

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

:


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

要添加到这一点,您几乎不需要指向接口类型的指针。下面已经是一个指针。“如果您想在函数中接收指向需要接口类型的类型的指针,请使用指针接收器实现接口,就像您在第二个示例中所做的那样。”--您可以添加一些代码来演示这一点吗?我认为这是我尝试过的,但显然我的第二个例子不起作用。你能给我看一些工作代码吗?我可以在那里收到一个指针,指向一个需要接口类型的函数中的类型?@LoneLearner,是的。留心岗位。半小时后我会更新它。@LoneLearner,抱歉耽搁了。这是您的代码片段,带有注释和打印类型。我希望这会有帮助。@LoneLearner,invokeHello接收接口类型,但不接收指向接口的指针。我仍然感到困惑。您的代码示例似乎与我的第一个示例(在我的问题中)相同。在我的第一个示例中,
invokeHello
接收接口类型(不是指针)。
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)
}