2014-12-28 6 views
2

У меня есть этот контроллер:ошибка Отражение на GoLang - Слишком мало аргументов

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 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) 
     } 
    } 
} 

И это выполняется таким образом:

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

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

проблема скомпилирована. Она не показывает какие-либо ошибки, но когда я иду на сайт, просто указывая на локальном хосте, он показывает:

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 

Я не могу найти какую-либо ошибку, и это более странно, он компилирует нормально ... Я m new in Go, поэтому я понятия не имею, что происходит ...

ответ

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) 

Фактически, это то, что я уже делал, но не так.

+2

Интересное использование утверждения типа там. +1. Точнее, чем мой ответ. – VonC

0

Как объясняется в «How to properly use .Call in reflect package, Golang?», а в reflect#Value.Call() вам нужен фрагмент с по крайней мере 1 элементом нужного типа, если ваша функция принимает один параметр.

Если вы знаете точный тип и значение параметра, вам нужно создать, и построить свой параметр вызова:

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

Исключение «reflect: Call with too few input arguments» называется после checking the number of parameters expected by the function

NumIn возвращается число входных параметров типа функции.

+0

Большое спасибо за помощь. Когда вы читаете мой вопрос, я новичок. Поэтому я получаю, вроде, ваш ответ. В коде вы видите, что аргумент, который он получает, является HTTP-запросом, поэтому в каждом запросе он будет отличаться. Как я могу создать его в вызове? Еще раз спасибо! – Cito

+0

@Cito не уверен, учитывая, что вы * нуждаетесь *, чтобы передать правильный список параметров для каждой функции 'Call()'. Если имя функции недостаточно для того, чтобы вы могли угадать правильное значение для передачи, это может быть проблемой. – VonC

+1

Я сделал это вот так: 'methodInterface: = finalMethod.Call ([] reflect.Value {reflection.ValueOf (r)}) [0] .Interface()' Но теперь ошибка: 'interface conversion: интерфейс - это строка, а не func (* http.Request) (строка, int) ' – Cito

Смежные вопросы