這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
-
- 起因
- 通過反射擷取struct指定的方法
- 通過json字串調用
- 適當的完善
起因
在很多場合會存在這樣一個需求或者想法:提交一個類似這樣的json
{ "func_name":"FooBarAdd", "params":[ 123.4, 432.1 ]}
然後得到一個這樣的json
{ "func_name":"FooBarAdd", "data":[ 555.5 ]}
要達到這樣的目的,必須要先解析提交的json, 擷取到方法名和參數,然後找到擁有這個方法的實體,將參數做適當的類型轉換後調用方法,最後將得到的結果封裝成json返回。
至於這個json是通過http提交與返回,還是通過websocket提交與返回,抑或是通過tcp直接提交與返回,都是可以的。下面來看一下如何達到這個目的。
通過反射擷取struct指定的方法
假設現在有一個struct是這樣的
type FooBar struct {}func (f *FooBar) FooBarAdd(argOne, argTwo float64) float64 { return argOne + argTwo}
對於BarFuncAdd方法,可以這樣調用:
foobar := &FooBar{}resultCallByName :=reflect.ValueOf(foobar).MethodByName("FooBarAdd"). Call([]reflect.Value{reflect.ValueOf(123.4),reflect.ValueOf(432.1)})fmt.Println(resultCallByName[0].Float())
也可以這樣調用:
foobar := &FooBar{}resultCallByIndex :=reflect.ValueOf(foobar).Method(0). Call([]reflect.Value{reflect.ValueOf(123.4),reflect.ValueOf(432.1)})fmt.Println(resultCallByIndex[0].Float())
結果都是555.5
通過json字串調用
如果想用一串這樣的json
{ "func_name":"FooBarAdd", "params":[ 123.4, 432.1 ]}
得到一個這樣的結果
{ "func_name":"FooBarAdd", "data":[ 555.5 ]}
則可以這樣調用
foobar := &FooBar{}jsonData := ` { "func_name":"FooBarAdd", "params":[ 123.4, 432.1 ] }`type RequestInfo struct { FuncName string `json:"func_name"` Params []interface{} `json:"params"`}type ResultInfo struct { FuncName string `json:"func_name"` Data []interface{} `json:"data"`}requestInfo := &RequestInfo{}json.Unmarshal([]byte(jsonData), &requestInfo)resultCallByJson :=reflect.ValueOf(foobar).MethodByName(requestInfo.FuncName). Call([]reflect.Value{reflect.ValueOf(requestInfo.Params[0]), reflect.ValueOf(requestInfo.Params[1])})result := &ResultInfo{FuncName:requestInfo.FuncName, Data: []interface{{resultCallByJson[0].Interface()}}jsonResult, _ := json.Marshal(&result)fmt.Printf("%s\n", jsonResult)
適當的完善
是不是覺得還少了點什麼,比如要是參數個數不匹配怎麼辦?類型轉化怎麼處理?如何做到更通用比如像這樣調用:
jsonDataBarFuncSwap := `{ "func_name":"BarSwap", "params":[ 0.1, 0.9 ]}`result:=string(reflectinvoke.InvokeByJson([]byte(jsonStr))
完整的代碼範例,請看github上面的代碼 。