How can I define an implementation of Go interface method that receives pointer?

huangapple go评论89阅读模式
英文:

How can I define an implementation of Go interface method that receives pointer?

问题

以下是翻译好的内容:

以下程序运行正常。

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)

我该如何修复第二个程序?

英文:

The following program runs fine.

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

Here is the output.

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

But when I change the Hello method to receive a pointer, I get errors.

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

Here are the errors.

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

How can I fix the second program?

答案1

得分: 3

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

p 是类型 *Person*Joker 实现了接口 Person,将 invokeHello 修改为:

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

这样可以修复第二个程序。

我认为你对 golang 接口类型 有一些误解。

接口类型指定了一个称为其接口的方法集。接口类型的变量可以存储具有方法集的任何超集的任何类型的值。这样的类型被称为实现了该接口。

英文:
func invokeHello(p *Person) {
    p.Hello()
}

p is type *Person, *Joker implement interface Person, revert invokeHello to:

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

this will fix the second program.

I think you have misleading about golang interface type

> An interface type specifies a method set called its interface. A variable of interface type can store a value of any type with a method set that is any superset of the interface. Such a type is said to implement the interface.

答案2

得分: 0

修复

你不能使用指向interface类型的指针。
问题在于:

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

应该改为:

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

接口实现

类型实现接口。如果类型具有与接口声明的方法相匹配的方法,那么该类型就实现了该接口。

> 在Go中,接口提供了指定对象行为的方式:如果某个东西可以做到这一点,那么它就可以在这里使用。

类型 vs 类型的指针

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

如果你想在一个期望接口类型的函数中接收一个类型的指针,可以使用指针接收器来实现接口,就像你在第二个示例中所做的那样。

示例

type Person interface {
    Hello()
}

type Joker struct {
    Name string
}

/*
Hello方法使用指针接收器声明,这意味着指向Joker类型(*Joker)的指针而不是Joker类型本身实现了Person接口。
*/
func (j *Joker) Hello() {
    fmt.Println(j.Name, "says, \"Hello!\"")
}

/*
invokeHello接收满足Person接口的任何类型。
在这种情况下,传入的是Joker类型的指针。
*/
func invokeHello(p Person) {
    p.Hello()
}

func main() {
    i := Joker{"Peter"}
    j := &i
    // 注意类型之间的差异
    fmt.Printf(
        "Joker类型:%s\nJoker类型的指针:%s\n",
        reflect.TypeOf(i), reflect.TypeOf(j))
    invokeHello(j)
}

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

英文:

Fix

You can't use pointers to interface type.
That is the problem:

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

Should be:

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

Interface implementation

Types implement interfaces. If type has methods appropriate to a methods declared in an interface than the interface is implemented by the type.

> Interfaces in Go provide a way to specify the behavior of an object: if something can do this, then it can be used here.

Types vs pointers to a types

Type and *Type are different types. For example *Type could implement an interface but Type can not implement it. But *InterfaceType really has no sence to use.

If you want to receive pointer to a type in a function which expects an interface type, implement the interface with pointer receiver, like you did in a second example.

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

Otherwise if you want to receive a value of a type, implement the interface with value receiver, like you did in a first example.

huangapple
  • 本文由 发表于 2017年4月25日 12:50:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/43601858.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定