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?
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.
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()
}
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.
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.
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
Pointer to Joker type: %s
",
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.