Reputation: 10413
The following code works nicely:
package main
import (
"fmt"
)
func WrapperFunc(fn func(int,int) int) int{
return fn(3,4)
}
func add(a,b int) int{
return a + b
}
func main(){
fmt.Println(WrapperFunc(add))
}
I want to pass additional parameters that implements a specific interface. For instance, I modify the code as follows:
import (
"fmt"
)
type RequestBody interface {
GetDescription() string
}
type LoginRequest struct {
Username string
Password string
}
func (lr LoginRequest) GetDescription() string{
return "cool function"
}
func WrapperFunc(fn func(int, int, RequestBody) int) int {
lr := LoginRequest{}
return fn(3, 4, lr)
}
func add(a, b int, lr LoginRequest) int {
fmt.Println(lr.GetDescription())
return a + b
}
func main() {
fmt.Println(WrapperFunc(add))
}
It fails with the error below:
cannot use add (type func(int, int, LoginRequest) int) as type func(int, int, RequestBody) int in argument to WrapperFunc
However, when I do not implement the GetDescription
as below:
package main
import (
"fmt"
)
type RequestBody interface {
GetDescription() string
}
type LoginRequest struct {
Username string
Password string
}
func WrapperFunc(fn func(int, int, RequestBody) int) int {
lr := LoginRequest{}
return fn(3, 4, lr)
}
func add(a, b int, lr LoginRequest) int {
return a + b
}
func main() {
fmt.Println(WrapperFunc(add))
}
It fails with second error, as interface is not implemented (as expected).
cannot use lr (type LoginRequest) as type RequestBody in argument to fn:
LoginRequest does not implement RequestBody (missing GetDescription method)
cannot use add (type func(int, int, LoginRequest) int) as type func(int, int, RequestBody) int in argument to WrapperFunc
So, it understands that, in WrapperFunc
body, I can only call fn
with int
, int
and an RequestBody interface
that implements the GetDescription
, yet I still cannot pass it in the function phase. How can I accomplish this? I want to wrap functions that can have parameters that their type can change.
Upvotes: 3
Views: 2422
Reputation: 417502
The problem is that WrapperFunc()
expects a value of function type:
func(int, int, RequestBody) int
And you try to pass add
to it which has a function type:
func(int, int, LoginRequest) int
2 function types are equal if both have the same parameter and result types. This does not hold in the above mentioned 2 function types: RequestBody
and LoginRequest
are different types, and so function types having these as (or among) parameters are different types.
You may only pass add
to WrapperFunc()
if you change its parameters to match the required type:
func add(a, b int, lr RequestBody) int {
fmt.Println(lr.GetDescription())
return a + b
}
Now add()
has the same function type as fn
in the parameters of WrapperFunc()
, so your code will compile and run.
Output (try it on the Go Playground)
cool function
7
Notes:
Now lr
parameter in add()
is of type RequestBody
and not LoginRequest
. You may use it like a RequestBody
, which is you may call its GetDescription()
method. In WrapperFunc()
you don't have to change anything, as LoginRequest
implements RequestBody
, so it is allowed to call fn()
with a value of LoginRequest
, and an interface value of type RequestBody
will automatically, implicitly be created and passed to fn
(which is add()
in your case).
Note that in add()
since parameter is now a RequestBody
, you can't refer to fields of LoginRequest
. You may if the value implementing the interface is indeed a value of type LoginRequest
, in which case you may use type assertion to obtain the wrapped LoginRequest
value should you need it.
Upvotes: 2