samedi 18 janvier 2020

implement a generic argument method in GO

I have a code in GO, which includes many execution methods. Each method receives it own struct of parameters. I want a dispatcher to call each method with its related struct.

The dispatcher receives the name of the execution method, and a JSON of the parameters struct. Then, it uses reflection to build the struct, and calls the method.

The problem is I get compilation error unless I create the execution methods using empty interface. In the example below I have 2 execution methods: api1 is compiling, but is using the empty interface and explicit casting. api2 is what I want to do, but it is failing with compile error:

cannot use api2 (type func(Api2Parameters)) as type Api in assignment

How can I make api2 usage compile?

import (
    "encoding/json"
    "log"
    "reflect"
)

type Api func(arguments interface{})

type ApiDetails struct {
    Executor       *Api
    ParametersType reflect.Type
}

var Apis map[string]*ApiDetails

func RunApi(apiName string, data string) {
    api := Apis[apiName]
    parameters := reflect.New(api.ParametersType).Interface().(interface{})
    _ = json.Unmarshal([]byte(data), parameters)
    (*api.Executor)(parameters)
}

type Api1Parameters struct {
    Count1 int
    Id1    string
}

func api1(arguments interface{}) {
    parameters, _ := arguments.(*Api1Parameters)
    log.Printf("api1 parameters(%+v)", parameters)
}

type Api2Parameters struct {
    Count2 int
    Id2    string
}

func api2(arguments Api2Parameters) {
    log.Printf("api2 parameters(%+v)", arguments)
}

func Test() {
    // this assignment works fine
    var api_1 Api = api1
    Apis["api1"] = &ApiDetails{
        Executor:       &api_1,
        ParametersType: reflect.TypeOf(Api1Parameters{}),
    }

    // this assignment produce compile error
    var api_2 Api = api2
    Apis["api2"] = &ApiDetails{
        Executor:       &api_2,
        ParametersType: reflect.TypeOf(Api2Parameters{}),
    }

    RunApi("api1", `{"Count1":19, "Id1":"a"}`)
    RunApi("api2", `{"Count2":34, "Id2":"b"}`)
}




Aucun commentaire:

Enregistrer un commentaire