Go 1.18
You can now have parametrized structs:
type ResponseListDataPayload[T any] struct {
List []T `json:"list"` //generic
TotalCnt int64 `json:"totalCnt"`
Page int64 `json:"page"`
Step int64 `json:"step"`
}
Remember that generic structs must be instantiated with an explicit type parameter:
queryResults := []*model.SomeModel{}
responseResult := &ResponseListDataPayload[*model.SomeModel]{
List: queryResults,
// other fields
}
If you want to improve code reuse even more and "genericize" also the struct initialization, you can use a constructor function. Functions can take advantage of type inference to omit writing out the type arguments:
// add to func signature other arguments as needed
func NewResponseFor[T any](list []T) *ResponseListDataPayload[T] {
return &ResponseListDataPayload[T]{ List: list }
}
and use it as:
queryResults := // some query results
responseResult := NewResponseFor(queryResults)
Example: https://gotipplay.golang.org/p/jYTHegaeubR
Go 1.17 and below
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{}
.