douba9020 2018-02-26 18:51
浏览 34
已采纳

如何使函数的参数成为“通用”结构

For example, I want to write a method like this:

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
}

The problem of this code is: If I don't want to parse UserCommand but any other such as ProductCommand, I must write the same code, only different at line: command := UserCommand{}. So my question is: how can I generic this code.

I have tried this solution but it doesn't work:

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{})

But it doesn't work. It return array of map[string]interface{} How can I fix this.

Edit:

Here is some my defined struct

type UserCommand struct {
    User string
    Info string
}
type ProductCommand struct {
    Name      string
    Quanlity  int
}
  • 写回答

1条回答 默认 最新

  • doupaxia2478 2018-02-27 07:02
    关注
    // I want to be able to call this method
    parseData(data, UserCommand{})
    

    It is possible to support this style of "generic" signature by using Go's reflect package.

    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
    ", parsed)
    
        data = []json.RawMessage{
            json.RawMessage(`{"Name":"n1","Quantity":1}`),
            json.RawMessage(`{"Name":"n2","Quantity":2}`),
        }
        parsed = parseData(data, ProductCommand{})
        fmt.Printf("%#v
    ", parsed)
    }
    

    The output shows that the first parseData call has parsed two UserCommand structs and the second call has parsed two ProductCommand structs.

    []interface {}{main.UserCommand{User:"u1", Info:"i1"}, main.UserCommand{User:"u2", Info:"i2"}}
    []interface {}{main.ProductCommand{Name:"n1", Quantity:1}, main.ProductCommand{Name:"n2", Quantity:2}}
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大
  • ¥15 Oracle中如何从clob类型截取特定字符串后面的字符
  • ¥15 想通过pywinauto自动电机应用程序按钮,但是找不到应用程序按钮信息
  • ¥15 如何在炒股软件中,爬到我想看的日k线
  • ¥15 seatunnel 怎么配置Elasticsearch
  • ¥15 PSCAD安装问题 ERROR: Visual Studio 2013, 2015, 2017 or 2019 is not found in the system.
  • ¥15 (标签-MATLAB|关键词-多址)
  • ¥15 关于#MATLAB#的问题,如何解决?(相关搜索:信噪比,系统容量)
  • ¥500 52810做蓝牙接受端
  • ¥15 基于PLC的三轴机械手程序