Reflection error on GoLang - Too few arguments - go

I have this controller:
package web
import (
"net/http"
)
func init() {
}
func (controller *Controller) Index(r *http.Request) (string, int) {
return "Testing", http.StatusOK
}
With this handler:
type Application struct {
}
func (application *Application) Route(controller interface{}, route string) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
var ptr reflect.Value
var value reflect.Value
var finalMethod reflect.Value
value = reflect.ValueOf(controller)
// if we start with a pointer, we need to get value pointed to
// if we start with a value, we need to get a pointer to that value
if value.Type().Kind() == reflect.Ptr {
ptr = value
value = ptr.Elem()
} else {
ptr = reflect.New(reflect.TypeOf(controller))
temp := ptr.Elem()
temp.Set(value)
}
// check for method on value
method := value.MethodByName(route)
if method.IsValid() {
finalMethod = method
}
// check for method on pointer
method = ptr.MethodByName(route)
if method.IsValid() {
finalMethod = method
}
methodInterface := finalMethod.Call([]reflect.Value{})[0].Interface()
method_route := methodInterface.(func(r *http.Request) (string, int))
body, code := method_route(r)
switch code {
case http.StatusOK:
io.WriteString(w, body)
case http.StatusSeeOther, http.StatusFound:
http.Redirect(w, r, body, code)
default:
w.WriteHeader(code)
io.WriteString(w, body)
}
}
}
And it is executed in this way:
controller := &web.Controller{}
application := &system.Application{}
http.HandleFunc("/", application.Route(controller, "Index"))
The problem is it compiled ok. It does not show any error, but when I go to the website, just by pointing at localhost, it shows:
2014/12/27 22:38:16 http: panic serving 127.0.0.1:58304: reflect: Call with too few input arguments
goroutine 20 [running]:
net/http.funcĀ·011()
/usr/local/Cellar/go/1.3.3/libexec/src/pkg/net/http/server.go:1100 +0xb7
I cannot find any error, and it is more strange it compiles ok... I'm new in Go, so I've no idea what is going on...

I have found the answer by reading this:
https://stackoverflow.com/a/20715067/1339973
So instead of trying to call the method:
methodInterface := finalMethod.Call([]reflect.Value{})[0].Interface()
method_route := methodInterface.(func(r *http.Request) (string, int))
body, code := method_route(r)
I just get the interface I need, then convert it into a function and call it as such.
methodInterface := finalMethod.Interface()
method_route := methodInterface.(func(r *http.Request) (string, int))
body, code := method_route(r)
Actually, that is kind of what I was already doing, but in the wrong way.

As explained in "How to properly use .Call in reflect package, Golang?", and in reflect#Value.Call(), you need a slice with at least 1 element of the right type in it, if your function takes one parameter.
If you know the exact parameter type and value, you need to create it, and build your Call parameter:
in := []reflect.Value{reflect.ValueOf(m)}
The exception "reflect: Call with too few input arguments" is called after checking the number of parameters expected by the function
NumIn returns a function type's input parameter count.

Related

Why is this function's argument not being invoked as a function?

Here is the complete example from my current reading material "Hands-On Restful Web Services With Go" from Packt.
func filterContentType(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
log.Println("Currently in the check content type middleware")
// Filtering requests by MIME type
if r.Header.Get("Content-type") != "application/json" {
w.WriteHeader(http.StatusUnsupportedMediaType)
w.Write([]byte("415 - Unsupported Media Type. Please send JSON"))
return
}
handler.ServeHTTP(w, r)
})
}
func setServerTimeCookie(handler http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// Setting cookie to every API response
cookie := http.Cookie{Name: "ServerTimeUTC", Value: strconv.FormatInt(time.Now().Unix(), 10)}
http.SetCookie(w, &cookie)
log.Println("Currently in the set server time middleware")
handler.ServeHTTP(w, r)
})
}
func handle(w http.ResponseWriter, r *http.Request) {
// Check if method is POST
if r.Method == "POST" {
var tempCity city
decoder := json.NewDecoder(r.Body)
err := decoder.Decode(&tempCity)
if err != nil {
panic(err)
}
defer r.Body.Close()
// Your resource creation logic goes here. For now it is plain print to console
log.Printf("Got %s city with area of %d sq miles!\n", tempCity.Name, tempCity.Area)
// Tell everything is fine
w.WriteHeader(http.StatusOK)
w.Write([]byte("201 - Created"))
} else {
// Say method not allowed
w.WriteHeader(http.StatusMethodNotAllowed)
w.Write([]byte("405 - Method Not Allowed"))
}
}
func main() {
originalHandler := http.HandlerFunc(handle)
http.Handle("/city", filterContentType(setServerTimeCookie(originalHandler))) // !
http.ListenAndServe(":8000", nil)
}
This program simply consists of the main function and 3 other functions, their logic is arbitrary and just copied from my book's example.
At bottom, where I've commented with "!", filterContentType is using an argument that itself is a function (setServerTimeCookie), and it looks like it's being invoked with originalHandler as its argument.
However when this code is run, the order of execution is:
filterContentType 2. setServerTimeCookie 3. originalHandler
This is counterintuitive to what I understand about using functions as arguments. I assumed that setServerTimeCookie would be the first to execute but that's not the case; it's behaving like an uninvoked function.
This leads to my question, what is causing setServerTimeCookie to defer its execution despite the syntax suggesting it's being invoked as filterContentType's argument?
I attempted to simplify things for my own understanding:
func main() {
one(two(three))
}
func one(f func()) {
fmt.Println("ONE\n")
f()
}
func two(f func()) {
fmt.Println("TWO\n")
f()
}
func three(){
fmt.Println("THREE\n")
}
This code does not build, I'm left with the error:
two(three) used as value -which tells me that two is being invoked, unlike the book's example.
What's the difference and again, why doesn't the book's example invoke setServerTimeCookie first? My only assumption is that it has something to do with the implementation of http.HandlerFunc so maybe I should start there.
Any insight to fast-forward my understanding would be greatly appreciated.
This doesn't compile because two(three) does not return a value.
I assume you want to return a function closure in this case, so to fix:
func two(f func()) func() {
return func() {
fmt.Println("TWO\n")
f()
}
}
https://go.dev/play/p/vBrAO6nwy4X
Circling back to your question about setServerTimeCookie and it's use of return http.HandlerFunc(fn). Looking at the source for http.HandlerFunc reveals it's actually a type definition - and NOT a conventional function call. It's actual IMHO the most powerful and underrated four lines of code in the go standard library:
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
By creating this value of http.HandlerFunc, it's implicitly a http.Handler, since it provides the ServeHTTP method. This therefore allows this method to be called upon request - which is exactly what a webservice is designed to do: the underlying function f will be invoked when the handler is invoked.
Because in the expression one(two(three)) function two is not passed as function reference. Instead function two is called with the argument tree, which is not what function one expects

Returning an error from HandlerFunc - need a new type

Right now I have this:
type AppError struct{
Status int
Message string
}
func (h NearbyHandler) makeUpdate(v NearbyInjection) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
item, ok := v.Nearby[params["id"]]
if !ok {
return AppError{
500, "Missing item in map.",
}
}
}
}
the problem is that if I do this:
func (h NearbyHandler) makeUpdate(v NearbyInjection) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) AppError { // <<< return AppError
}
}
that won't compile b/c http.HandlerFunc doesn't return a function which returns AppError.
Another question I have, how can I avoid explicitly returning nil if if I use AppError as the return value?
Note that I get this error:
cannot use func literal (type func(http.ResponseWriter, *http.Request)
AppError) as type http.HandlerFunc in return argument
So instead of returning the status for the request the designers of go give you the ResponseWriter. This is your main interaction with the client. For example to set a status code, do WriteHeader(500).
that won't compile b/c http.HandlerFunc doesn't return a function which returns AppError.
Why you don't handle error directly in makeUpdate method?
how can I avoid explicitly returning nil if if I use AppError as the return value?
Cannot use 'nil' as type AppError in return argument, you can use the initial value, like this:
func test() AppError {
ret := AppError{
200, "OK",
}
condition := true // some condition
if !condition {
ret.Status = 500
ret.Message = "internal error"
}
return ret
}
It's a server and a handler shouldn't return an error, as it was said you should simply notify the client that an error was encountered while processing the request. Determine the error type and output the corresponding http code and optional message body.
Now, if by chance, your server has some other goroutines that need to be notified of the error you can signal to them through a channel (for metrics or things like that), so you can that way use the error in any way you wish outside the handler scope.

Chaining middleware in net/http golang

I am trying to add context to Authorization middleware. The ContextHandler is a handler which will be passed to api handlers to take care of connections and config variables. A struct Method ServeHTTP also has been added to the ContextHandler so that it satisfies the net/Http interface for handling requests properly.
CheckAuth is the middle ware which takes in the request to check token validation etc, If token is valid, executes the ServeHTTP method and if not, Returns the appropriate error in the response.
Code compiles, but i am getting error in the ServeHTTP method.
type ContextHandler struct {
*AppContext
Handler func(*AppContext, http.ResponseWriter, *http.Request)(int, error)
}
type AppContext struct {
Db *mgo.Session
Config *simplejson.Json
}
func (ah *ContextedHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
status, err := ah.handler(ah.AppContext, w, r)
if err != nil {
switch status {
case http.StatusNotFound:
http.NotFound(w, r)
case http.StatusInternalServerError:
http.Error(w, http.StatusText(status), status)
default:
http.Error(w, http.StatusText(405), 405)
}}}
func CheckAuth(h http.Handler) http.Handler {
log.Println("Entered in CheckAuth")
f := func( w http.ResponseWriter, r *http.Request) {
authorizationToken := r.Header.Get("Authorization")
if authorizationToken != ""{
secret := []byte("somejunk")
var credentials authorization
token, err := jwt.ParseWithClaims(authorizationToken, &credentials, func(t *jwt.Token) (interface{}, error) {
return []byte(secret), nil
})
if err == nil && token.Valid {
//If everything is fine serve the Http request
h.ServeHTTP( w, r)
return
} else {
//Some response returned
json.NewEncoder(w).Encode(response)
return
}
//Check if user exists in the database
if dberr != nil {
//SOmeresponse to be returned
json.NewEncoder(w).Encode(response)
return
}
}else{
response := simplejson.New()
//response authorization header is missing
json.NewEncoder(w).Encode(response)
return
}
}
return http.HandlerFunc(f)
}
func Initdb(configfile *simplejson.Json) *mgo.Session {
//return mongodbsession, copy and close while using it
}
In main.go file in the parent package
func main() {
var FileUploadContextHandler *ContextedHandler = &ContextedHandler{&context, filesystem.FileUpload}
router.Methods("POST").Path("/decentralizefilesystem/fileupload").Name("FileUpload").Handler(CheckAuth(FileUploadContextHandler))
}
I am getting this error
2018/07/08 20:45:38 http: panic serving 127.0.0.1:52732: runtime error: invalid memory address or nil pointer dereference
goroutine 35 [running]:
net/http.(*conn).serve.func1(0xc4202ce140)
/usr/local/go/src/net/http/server.go:1726 +0xd0
panic(0x6fe680, 0x92cb10)
/usr/local/go/src/runtime/panic.go:502 +0x229
gitlab.com/mesha/Gofeynmen/vendor/gopkg.in/mgo%2ev2.(*Session).Copy(0x0, 0x7ff9485fb060)
/home/feynman/goworkspace/src/gitlab.com/mesha/Gofeynmen/vendor/gopkg.in/mgo.v2/session.go:1589 +0x22
gitlab.com/mesha/Gofeynmen/appsettings.CheckAuth.func1(0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
/home/feynman/goworkspace/src/gitlab.com/mesha/Gofeynmen/appsettings/appsettings.go:115 +0x361
net/http.HandlerFunc.ServeHTTP(0xc420290180, 0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
/usr/local/go/src/net/http/server.go:1947 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc42024a310, 0x7ff9485fb060, 0xc420276300, 0xc4202e4200)
/home/feynman/goworkspace/src/github.com/gorilla/mux/mux.go:162 +0xed
github.com/gorilla/handlers.loggingHandler.ServeHTTP(0x7a8120, 0xc42000e018, 0x7a7b20, 0xc42024a310, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
/home/feynman/goworkspace/src/github.com/gorilla/handlers/handlers.go:69 +0x123
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc4202c4090, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
/home/feynman/goworkspace/src/github.com/gorilla/handlers/cors.go:52 +0xa3b
net/http.serverHandler.ServeHTTP(0xc4202da0d0, 0x7aad60, 0xc4202f0000, 0xc4202e4000)
/usr/local/go/src/net/http/server.go:2694 +0xbc
net/http.(*conn).serve(0xc4202ce140, 0x7ab120, 0xc42025e100)
/usr/local/go/src/net/http/server.go:1830 +0x651
created by net/http.(*Server).Serve
/usr/local/go/src/net/http/server.go:2795 +0x27b
It's likely an attempt to dereference ah from (ah *ContextedHandler), when ah is not a pointer to a ContextedHandler.
The types in this assignment don't match up:
var FileUploadContextHandler *ContextedHandler =
ContextedHandler{&context, filesystem.FileUpload}
On the left side you have type *ContextedHandler. On the right side you have type ContextedHandler.
Did you mean
var FileUploadContextHandler *ContextedHandler =
&ContextedHandler{&context, filesystem.FileUpload}
Or did you mean
var FileUploadContextHandler ContextedHandler =
ContextedHandler{&context, filesystem.FileUpload}
?
The argument passed to the CheckAuth function appears to not match the function signature either:
CheckAuth(FileUploadContextHandler)
FileUploadContextHandler is type *ContextedHandler. The function signature is:
func CheckAuth(h contextHandlerFunc) contextHandlerFunc
The type definition of contextHandlerFunc does not appear to be part of the code you shared.
A problem with this line:
router.Methods("POST").Path("/decentralizefilesystem/fileupload").Name("FileUpload").Handler(CheckAuth(FileUploadContextHandler))
...would be easier to track down if you broke it up into variable assignments on several lines and then figured out which line the panic pointed to.

How to instantiate value of unknown type in Go?

I develop some server in golang. I try to create some wrapper-function, which can helps me in future.
What I have:
1) I had some DTO structs, for example:
type Request struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
}
type Response struct {
Field1 string `json:"field1"`
Field2 string `json:"field2"`
Field3 string `json:"field3"`
}
2) I had some functions, in controller layer, which (by conventions) receives 1 argument (pointer to struct) and returns 1 result (pointer to struct), for example:
func SomeHandler(request *Request) *Response{
...do something
return &Response{"first","second","third"}
}
What I need:
I need to write wrapper function which receives as argument:
pointer to 'controller' function
http.ResponseWriter
*http.Request
This wrapper function must:
Determine type of argument of 'controller' function
Determine type of result of 'controller' function
Instantiate and fill argument value from Body of *http.Request (decode from json)
Call controller Function with instantiated on previous step argument
Write results of previous step into http.ResponseWriter (encoded as json)
Wrapper must work correct with any types of 'controller' functions - signatures of this functions is different (different argument type, different result type)
Can anybody help me with implementing of this wrapper?
What you're doing is a bit weird but reflect can provide all the info you need.
func myFunction(a string, b int32) error {
return nil
}
func myWrapper(mystery interface{}) {
typ := reflect.TypeOf(mystery)
// Check typ.Kind before playing with In(i);
for i := 0; i < typ.NumIn(); i++ {
fmt.Printf("Param %d: %v\n", i, typ.In(i))
}
for i := 0; i < typ.NumOut(); i++ {
fmt.Printf("Result %d: %v\n", i, typ.Out(i))
}
}
This prints:
Param 0: string
Param 1: int32
Result 0: error
Something like this should work (untested):
func wrapper(ctlr interface{}, w http.ResponseWriter, r *http.Request) error {
tpe := reflect.TypeOf(ctlr)
if tpe.Kind() != reflect.Func || tpe.NumIn() != 1 || tpe.NumOut() != 1 {
// TODO: handle wrong ctlr type
}
// 1. Determine type of argument of 'controller' function
argt := tpe.In(0)
// 2. Determine type of result of 'controller' function
// rest := tpe.Out(0) // commented out since it's useless
// 3. Instantiate and fill argument value from Body of *http.Request (decode from json)
arg := reflect.Zero(argt)
err := json.NewDecoder(r.Body).Decode(&arg)
if err != nil {
// TODO: handle err
}
// 4. Call controller Function with instantiated on previous step argument
resv := reflect.ValueOf(ctlr).Call([]reflect.Value{arg})[0]
// 5. Write results of previous step into http.ResponseWriter (encoded as json)
err = json.NewEncoder(w).Encode(resv.Interface())
if err != nil {
// TODO: handle err
}
return nil
}
Note that the second step is unnecessary.

Wrapper for arbitrary function in Go

Is it possible to create a wrapper for arbitrary function in Go that would take the same arguments and return the same value?
I'm not talking about the wrapper that would look exactly the same, it may look differently, but it should solve the problem.
For example the problem might be to create a wrapper of arbitrary function that first looks for the result of the function call in cache and only in case of cache miss executes the wrapped function.
Here's a solution using reflect.MakeFunc. This particular solution assumes that your transformation function knows what to do with every different type of function. Watch this in action: http://play.golang.org/p/7ZM4Hlcqjr
package main
import (
"fmt"
"reflect"
)
type genericFunction func(args []reflect.Value) (results []reflect.Value)
// A transformation takes a function f,
// and returns a genericFunction which should do whatever
// (ie, cache, call f directly, etc)
type transformation func(f interface{}) genericFunction
// Given a transformation, makeTransformation returns
// a function which you can apply directly to your target
// function, and it will return the transformed function
// (although in interface form, so you'll have to make
// a type assertion).
func makeTransformation(t transformation) func(interface{}) interface{} {
return func(f interface{}) interface{} {
// g is the genericFunction that transformation
// produced. It will work fine, except that it
// takes reflect.Value arguments and returns
// reflect.Value return values, which is cumbersome.
// Thus, we do some reflection magic to turn it
// into a fully-fledged function with the proper
// type signature.
g := t(f)
// typ is the type of f, and so it will also
// be the type that of the function that we
// create from the transformation (that is,
// it's essentially also the type of g, except
// that g technically takes reflect.Value
// arguments, so we need to do the magic described
// in the comment above).
typ := reflect.TypeOf(f)
// v now represents the actual function we want,
// except that it's stored in a reflect.Value,
// so we need to get it out as an interface value.
v := reflect.MakeFunc(typ, g)
return v.Interface()
}
}
func main() {
mult := func(i int) int { return i * 2 }
timesTwo := func(f interface{}) genericFunction {
return func(args []reflect.Value) (results []reflect.Value) {
// We know we'll be getting an int as the only argument,
// so this type assertion will always succeed.
arg := args[0].Interface().(int)
ff := f.(func(int) int)
result := ff(arg * 2)
return []reflect.Value{reflect.ValueOf(result)}
}
}
trans := makeTransformation(timesTwo)
// Since mult multiplies its argument by 2,
// and timesTwo transforms functions to multiply
// their arguments by 2, f will multiply its
// arguments by 4.
f := trans(mult).(func(int) int)
fmt.Println(f(1))
}
The answer based on #joshlf13 idea and answer, but seems more simple to me.
http://play.golang.org/p/v3zdMGfKy9
package main
import (
"fmt"
"reflect"
)
type (
// Type of function being wrapped
sumFuncT func(int, int) (int)
// Type of the wrapper function
wrappedSumFuncT func(sumFuncT, int, int) (int)
)
// Wrapper of any function
// First element of array is the function being wrapped
// Other elements are arguments to the function
func genericWrapper(in []reflect.Value) []reflect.Value {
// this is the place to do something useful in the wrapper
return in[0].Call(in[1:])
}
// Creates wrapper function and sets it to the passed pointer to function
func createWrapperFunction(function interface {}) {
fn := reflect.ValueOf(function).Elem()
v := reflect.MakeFunc(reflect.TypeOf(function).Elem(), genericWrapper)
fn.Set(v)
}
func main() {
var wrappedSumFunc wrappedSumFuncT
createWrapperFunction(&wrappedSumFunc)
// The function being wrapped itself
sumFunc := func (a int, b int) int {
return a + b
}
result := wrappedSumFunc(sumFunc, 1, 3)
fmt.Printf("Result is %v", result)
}
The best I've come up with is to take a function def and return an interface, which will need type assertion afterwards:
func Wrapper(metaParams string, f func() (interface{}, string, error)) (interface{}, error) {
// your wrapper code
res, metaResults, err := f()
// your wrapper code
return res, err
}
Then to use this also takes a little work to function like a wrapper:
resInterface, err := Wrapper("data for wrapper", func() (interface{}, string, error) {
res, err := YourActualFuntion(whatever, params, needed)
metaResults := "more data for wrapper"
return res, metaResults, err
}) // note f() is not called here! Pass the func, not its results
if err != nil {
// handle it
}
res, ok := resInterface.(actualType)
if !ok {
// handle it
}
The upside is this is somewhat generic, can handle anything with 1 return type + error, and doesn't require reflection.
The downside is this takes a lot of work to use as it's not a simple wrapper or decorator.
Building on previous answers and using Go's new generic capabilities, I believe this can be implemented quite elegantly (playground link):
package main
import (
"fmt"
"reflect"
)
// Creates wrapper function and sets it to the passed pointer to function
func wrapFunction[T any](function T) T {
v := reflect.MakeFunc(reflect.TypeOf(function), func(in []reflect.Value) []reflect.Value {
// This is the place to intercept your call.
fmt.Println("Params are:", in)
f := reflect.ValueOf(function)
return f.Call(in)
})
return v.Interface().(T)
}
func main() {
// The function being wrapped itself
sum := func(a int, b int) int {
return a + b
}
wrapped := wrapFunction(sum)
fmt.Printf("Result is %v", wrapped(1, 3))
}
Like this?
var cache = make(map[string]string)
func doStuff(key string) {
//do-something-that-takes-a-long-time
cache[key] = value
return value
}
fun DoStuff(key string) {
if v, ok := cache[key]; ok {
return v
}
return doStuff(key)
}

Resources