有没有办法以编程方式确定Go中函数的参数(序列和类型)?
我想动态地将HTTP请求转换为方法/ func调用,以避免编写重复的编组代码(是的,我知道我需要非常小心我暴露的方法以及可能涉及的安全风险)。如果我可以检查函数所需的参数,从请求中解析适当的值然后动态调用函数(看起来最后一步将使用reflect.Value.Call - 至少那部分似乎是直的),这似乎是可能的。向前)。
编辑:能够这样做的好处是你可以创建一个适合直接在Go和远程使用的方法。例如,如果您有这样的函数:
func UpdatePerson(p *Person) error { ... }
这显然可以在Go中使用;我希望能够通过HTTP公开外部。
使用json-rpc接近但看起来会(在某些情况下)需要一些更加苛刻的结构用于它上面的i / o。
编辑2:基本上我有一整套CRUD要编写,我想暴露部分DAO,而不必编写所有这些疯狂的编组编码来创建另一个处理HTTP内容的层。 (对于一些安全性敏感的东西,我需要更仔细地编写内容,但我的许多DAO函数应该直接从浏览器“ - 也可以从Go”调用。)json-rpc满足第一个要求,但不是必然是第二个。答案 0 :(得分:2)
如果我理解您要做的事情,那么您正在寻找json-rpc
。下面是一个非常简单的如何使用它的例子:
package main
import (
"github.com/gorilla/rpc"
"github.com/gorilla/rpc/json"
"net/http"
)
type MyArgs struct {
Msg string
}
type MyResponse struct {
Msg string
}
type MyService struct{}
func (h *MyService) Test(r *http.Request, args *MyArgs, response *MyResponse) error {
response.Msg = "Received: " + args.Msg
return nil
}
func main() {
s := rpc.NewServer()
s.RegisterCodec(json.NewCodec(), "application/json")
s.RegisterService(new(MyService), "")
http.Handle("/rpc", s)
http.ListenAndServe(":10000", nil)
}
用卷曲测试:
curl -X POST -H "Content-Type: application/json" \
-d '{"method":"MyService.Test","params":[{"Msg":"Test"}], "id":"1"}' \
http://localhost:10000/rpc
响应:
{"result":{"Msg":"Received: Test"},"error":null,"id":"1"}
编辑:
似乎有点混乱 - 你不需要Go两端 - 你可以使用jQuery从浏览器中调用方法,如下所示:
$.ajax({
url: '/rpc',
type:"POST",
data: JSON.stringify({"method":"MyService.Test","params":[{"Msg":"Test"}], "id":"1"}),
contentType:"application/json; charset=utf-8",
dataType:"json",
success: function(data){
console.log(data);
}
});
答案 1 :(得分:2)
您可以使用reflect
package确定功能的参数。例如:
// argument is interface{} so we can accept functions of any signature
func printArguments(f interface{}) {
t := reflect.TypeOf(f)
fmt.Println("Function arguments:")
for i := 0; i < t.NumIn(); i++ {
fmt.Printf(" %d. %v\n", i, t.In(i))
}
fmt.Println("Function return values:")
for i := 0; i < t.NumOut(); i++ {
fmt.Printf(" %d. %v\n", i, t.Out(i))
}
}
In
和Out
函数分别返回表示参数和返回值类型的reflect.Type
值。您可以使用此类型信息构造Value
个对象的参数向量,以使用。
您可以在此处使用此示例:http://play.golang.org/p/qLThrI_Cw9