如何使函数参数是一个"泛型"结构

时间:2018-02-26 18:51:31

标签: go struct

例如,我想写一个这样的方法:

func parseData(rawData []json.RawMessage) []interface{} {
    var migrations []interface{}
    for _, migration := range rawData {
        // this is an custom struct
        command := UserCommand{}
        json.Unmarshal(migration, &command)
        migrations = append(migrations, command)
    }

    return migrations
}

此代码的问题是:如果我不想解析UserCommand而不是ProductCommand之类的任何其他代码,我必须编写相同的代码,但只有不同的代码:{{ 1}}。所以我的问题是:我如何通用这个代码。

我尝试过这个解决方案,但它不起作用:

command := UserCommand{}

但它不起作用。它返回func parseData(rawData []json.RawMessage, class interface{}) []interface{} { var migrations []interface{} for _, migration := range rawData { command := class json.Unmarshal(migration, &command) migrations = append(migrations, command) } return migrations } // then I call this method parseData(data, UserCommand{}) 数组如何解决这个问题。

编辑:

这是我定义的一些结构

map[string]interface{}

1 个答案:

答案 0 :(得分:1)

class X {
    apples(){ return  "apples"; }
    pears(){ return  "pears"; }
    lemons(){ return  "lemons"; }

    // We use a genric function to ensure the type of values is a union on literal types not string
    static readonly values = (<T extends string>(v: T[]) => v)(['apples', 'pears', 'lemons'])
    callFunction (type: string){
        const index = X.values.indexOf(type as any);
        //If the value is not in the expected input we raise an error
        if(index == -1) throw "Value not ok";
        // Since values[index] is a union of apples | pears | lemons 
        // the type of this[X.values[index]] will be ()=> string 
        // inferred based on 
        return this[X.values[index]]();

    }
}

可以支持这种&#34;泛型&#34;使用Go的reflect包进行签名。

// I want to be able to call this method
parseData(data, UserCommand{})

输出显示第一个package main import ( "encoding/json" "fmt" "reflect" ) type UserCommand struct { User string Info string } type ProductCommand struct { Name string Quantity int } func parseData(rawData []json.RawMessage, class interface{}) []interface{} { var parsed []interface{} for _, elem := range rawData { // Create a pointer to a new zero value of the same type as `class`. command := reflect.New(reflect.TypeOf(class)) // Pass a pointer to the new value to `json.Unmarshal`. json.Unmarshal(elem, command.Interface()) // Insert the pointed-to new value into the output slice. parsed = append(parsed, command.Elem().Interface()) } return parsed } func main() { data := []json.RawMessage{ json.RawMessage(`{"User":"u1","Info":"i1"}`), json.RawMessage(`{"User":"u2","Info":"i2"}`), } parsed := parseData(data, UserCommand{}) fmt.Printf("%#v\n", parsed) data = []json.RawMessage{ json.RawMessage(`{"Name":"n1","Quantity":1}`), json.RawMessage(`{"Name":"n2","Quantity":2}`), } parsed = parseData(data, ProductCommand{}) fmt.Printf("%#v\n", parsed) } 调用解析了两个parseData结构,第二个调用解析了两个UserCommand结构。

ProductCommand