I've recently learnt that in the net/http
package, there's a pattern of usage that keeps confusing me most. It is function type conversion. It is like this:
(function a) ->convert to-> (type t)
(type t) ->implentments-> (interface i)
So, if there's a function that takes interface i
as its parameter, it will invoke the function a, this is the way net/http
implements it.
But when I write my own code, I've had many misunderstandings on this pattern. My code goes like this:
package main
import (
"fmt"
)
type eat interface {
eat()
}
type aaa func()
func (op *aaa) eat() {//pointer receiver not right
fmt.Println("dog eat feels good")
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func feelsGood(a eat) {
a.eat()
}
func main() {
b := aaa(dog)
feelsGood(b)
}
//error:aaa does not implement eat (eat method has pointer receiver)
Type aaa has method eat, the same function name and parameter signature, which conforms to the rule of interface eat, but why does it give that error? Does the receiver matter?
Another question is with only a function and type, excluding an interface, the code goes like this:
package main
import (
"fmt"
)
type aaa func()
func (op *aaa) eat() {
op()
}
///////////////////////////////////////////////
func dog() {
fmt.Println("I'm a dog")
}
///////////////////////////////////////////////
func main() {
obj:=aaa(dog)
obj.eat()
}
//error:cannot call non-function op (type *aaa)
First, is op
an anonymous function, regardless of the error?
Second, it works well after I remove the asterisk, but why? op
is instance of type aaa
, receiver is op
, does op
stand for function dog()? The http package uses f(w,r)
the same way, but it is a little bit of hard to understand. Is op
a type, or an instance, or an anonymous function?
It seems like my comprehension of function converting is not right, but I've also checked many posts on Google, and none of them can teach me how to think of it and use it correctly.Thank you!
Question 1:
In Go, for a type T (like aaa in your case), T
and *T
have different method sets.
So, a value of type T can only access method:
func(t T)Foo() { ... }
While a value of type *T can access both methods:
func(t T)Foo() { ... }
func(t *T)Bar() { ... }
In your case, you have two options. Either you declare the eat
method for aaa
instead od *aaa
:
func (op aaa) eat() {
op()
}
Or you pass the pointer to b
to feelsGood
:
feelsGood(&b)
Question 2:
Yes, this question is related to the first. But in this case you can access the method because obj.eat()
will be short for (&obj).eat()
.
Your problem here is that you cannot call a function on the function pointer (op *aaa). Your options are to either create the method for aaa
instead of *aaa
:
func (op aaa) eat() {
op()
}
Or to call the op
function on the value and not the pointer:
func (op *aaa) eat() {
(*op)()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With