以下程序运行良好。
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)
如何修复第二个程序?
答案 0 :(得分:3)
func invokeHello(p *Person) {
p.Hello()
}
p
是*Person
类型,*Joker
实现接口Person
,将invokeHello
还原为:
func invokeHello(p Person) {
p.Hello()
}
这将修复第二个程序。
有误导接口类型指定称为其接口的方法集。接口类型的变量可以使用方法集存储任何类型的值,该方法集是接口的任何超集。据说这种类型实现了界面。
答案 1 :(得分:0)
您无法使用指向interface
类型的指针。
这就是问题:
func invokeHello(p *Person) {
p.Hello()
}
应该是:
func invokeHello(p Person) {
p.Hello()
}
类型实现接口。如果type具有适合于接口中声明的方法的方法,则该接口由该类型实现。
Go中的接口提供了一种指定对象行为的方法:如果有什么可以做到这一点,那么可以在这里使用它。
Type
和*Type
是不同的类型。例如,*Type
可以实现接口,但Type
无法实现它。但*InterfaceType
确实无法使用。
如果要接收指向期望接口类型的函数中的类型的指针,请使用指针接收器实现接口,就像在第二个示例中所做的那样。
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)
}
否则,如果您想要接收类型的值,请使用值接收器实现接口,就像您在第一个示例中所做的那样。