2017-10-06 18 views
2

反射関数呼び出しを作成していますが、現在は戻り値を取得しようとしています。反射呼び出しの結果を取得するGolang

例コード:

func (c *Client) Send(funcName protoFunction, data interface{}) (interface{}, error) { 
    funcList := c.GetProtoFuncList() 
    ctx := context.Background() 
    f := reflect.ValueOf(funcList[funcName.String()]) 
    vals := make([]reflect.Value, 2) 
    vals[0] = reflect.ValueOf(ctx) 
    vals[1] = reflect.ValueOf(data) 
    value := f.Call(vals) 
    log.Debug(value) 
    return nil, nil 
} 

どのように私は、「値」からの戻り値を取得しますし、それらを正しく返しますか? []reflect.Valueように関数コールの戻り値を返しValue.Call()

乾杯

+0

あなたはそれらを手に入れています。あなたのコードの 'value'は戻り値のスライスになります。あなたは何を持っているのですか? – Adrian

+0

['Call'署名](https://golang.org/pkg/reflect/#Value.Call)を見ると、あなたの' value'は '[] reflect.Value'です。あなたはこれを印刷します。何が問題なのですか? – JimB

+1

ちょうど不思議なことに、なぜ反射を使用するのですか。なぜそれを直接呼び出すのではなく、結果を返しますか? (インタフェース{}、エラー))(ctx、data) '?funcList [funcName.String()](func(context.Context、interface {})) (タイプアサーションは、異なるタイプの関数が 'funcList'に格納されている場合にのみ必要です;そうでなければ、それを取り除くことができ、' funcList [funcName.String()](ctx、data) 'を返します。 – icza

答えて

2

Value.Interface()メソッドを使用して、reflect.Valueで表される値をinterface{}値にすることができます。そこから、type assertionを使用してさまざまなタイプの値を取得できます。この単純な例では

同様:

var funcList = map[string]interface{}{ 
    "test": func(ctx context.Context, data interface{}) (interface{}, error) { 
     return "test-result-data:" + fmt.Sprint(data), errors.New("test-error") 
    }, 
} 

func Send(funcName string, data interface{}) (interface{}, error) { 
    f := reflect.ValueOf(funcList[funcName]) 
    params := []reflect.Value{ 
     reflect.ValueOf(context.Background()), 
     reflect.ValueOf(data), 
    } 
    res := f.Call(params) 

    ret := res[0].Interface() 
    var err error 
    if v := res[1].Interface(); v != nil { 
     err = v.(error) 
    } 
    return ret, err 
} 

テストそれ:

result, err := Send("test", "testData") 
fmt.Println(result, err) 

出力:

test-result-data:testData test-error 

しかし、これは不必要に複雑です。あなたはこのように、あなたはそれを直接呼び出し、直接結果を返すことがあり、機能を呼び出すためにリフレクションを使用する必要はありません。

func Send2(funcName string, data interface{}) (interface{}, error) { 
    return funcList[funcName].(func(context.Context, interface{}) (interface{}, error))(
     context.Background(), data, 
    ) 
} 

テストそれ:

result, err = Send2("test", "testData") 
fmt.Println(result, err) 

出力が同じです。 Go Playgroundの例を試してみてください。

+0

その明確な応答をありがとう。これはまさに私が必要としたものでした。 – Zander17

関連する問題