GoLang反射错误-参数过少

huangapple go评论79阅读模式
英文:

Reflection error on GoLang - Too few arguments

问题

我有这个控制器:

package web

import (
	"net/http"
)

func init() {

}

func (controller *Controller) Index(r *http.Request) (string, int) {
	return "Testing", http.StatusOK
}

使用这个处理程序:

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 value.Type().Kind() == reflect.Ptr {
			ptr = value
			value = ptr.Elem()
		} else {
			ptr = reflect.New(reflect.TypeOf(controller))
			temp := ptr.Elem()
			temp.Set(value)
		}

		// 检查值上的方法
		method := value.MethodByName(route)
		if method.IsValid() {
			finalMethod = method
		}
		// 检查指针上的方法
		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)
		}
	}
}

并且以这种方式执行:

controller := &web.Controller{}
application := &system.Application{}

http.HandleFunc("/", application.Route(controller, "Index"))

问题是它编译通过了。它没有显示任何错误,但是当我访问网站时,只需指向localhost,它显示:

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

我找不到任何错误,更奇怪的是它编译通过了... 我是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...

答案1

得分: 3

我通过阅读这篇文章找到了答案:

https://stackoverflow.com/a/20715067/1339973

所以,不再尝试调用方法:

    methodInterface := finalMethod.Call([]reflect.Value{})[0].Interface()
method_route := methodInterface.(func(r *http.Request) (string, int))
body, code := method_route(r)

我只是获取我需要的接口,然后将其转换为函数并调用它。

    methodInterface := finalMethod.Interface()
method_route := methodInterface.(func(r *http.Request) (string, int))
body, code := method_route(r)

实际上,这就是我之前一直在做的事情,只是方法不对。

英文:

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.

答案2

得分: 0

如在“如何正确使用 reflect 包中的 .Call,Golang?”和reflect#Value.Call()中所解释的,如果您的函数接受一个参数,那么您需要一个至少包含一个正确类型元素的切片。

如果您知道确切的参数类型和值,您需要创建它,并构建您的 Call 参数:

 in := []reflect.Value{reflect.ValueOf(m)}

异常“reflect: Call with too few input arguments”是在检查函数期望的参数数量之后被触发的。

> NumIn 返回函数类型的输入参数数量。

英文:

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.

huangapple
  • 本文由 发表于 2014年12月28日 12:42:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/27673747.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定