Home > Software engineering >  go using generic array in struct
go using generic array in struct

Time:09-17

We want to have

type ResponseListDataPayload struct {
    List     []*interface{} `json:"list"` //generic
    TotalCnt int64          `json:"totalCnt"`
    Page     int64          `json:"page"`
    Step     int64          `json:"step"`
}

and List could would accept []*model.someModel{}

queryResults := []*model.someModel{}
resposeResult := &ResponseListDataPayload{
    List:     queryResults,
    TotalCnt: cnt,
    Page:     pageInt,
    Step:     stepInt,
}

or []*model.anotherModel{}

queryResults := []*model.anotherModel{}
resposeResult := &ResponseListDataPayload{
    List:     queryResults,
    TotalCnt: cnt,
    Page:     pageInt,
    Step:     stepInt,
}

That's pretty straightforward in Java, could that be possible in go?

CodePudding user response:

could that be possible in go?

No, interface{} is not actually a generic type, it's just an interface with an empty method set.

Formally, you can assign any concrete value to it because assignability requires the value's method set to be a superset of the interface method set, and any set is a superset of the empty set ().

It's not the same thing as a parametrized type like Java's List<T> hence in Go []Foo is not assignable to []interface{}.

You must process the single elements in a loop:

var m []*model.anotherModel
// populate m
for _, v := range m {
    resp.List = append(resp.List, v)
}

Similarly, don't use pointers to the empty interface *interface{}. Use interface{} instead.

If your goal is to just serialize JSON (based on the presence of the tags on your struct), you can declare the List field as interface{} and you’ll be able to assign either of your slice values to it, for the reason stated above. Thus avoiding an extra slice manipulation. The json package will then serialize based on the concrete values boxed in the interface{}.

CodePudding user response:

In Go 1.18 you will be able to do something like, with real go generics:

func convert[S any](src []S) []interface{} {
    dst := make([]interface{}, 0, len(src))
    for _, v := range src {
        dst = append(dst, v)
    }
    return dst
}
//...
resp.List = convert(m)

But until 1.18 is out and more codebases embrace generics, you will still need to do the conversion by hand.

And like everyone said, don't use *interface{}.

  • Related