I have two structs that have the some of the same field names and types:
type JOURNAL_TAG struct {
DATE_START time.Time
DATE_END time.Time
ENTRY_NUMBER uint
VALUE float64
}
type INVENTORY_TAG struct {
DATE_START time.Time
DATE_END time.Time
PRICE float64
QUANTITY float64
ACCOUNT_NAME string
}
and I have a func that accesses the common field DATE_START
that should sort the slices of these types:
func sort_by_time[t JOURNAL_TAG|INVENTORY_TAG](slice []t, is_ascending bool) {
sort.Slice(slice, func(i, j int) bool {
return slice[i].DATE_START.After(slice[j].DATE_START) == is_ascending
})
}
Running go build
reports a compiler error:
slice[i].DATE_START undefined (type t has no field or method DATE_START)
I want to sort the slices of these two types using generics, is it possible?
I am using go 1.18.
CodePudding user response:
From the Go 1.18 release notes:
The Go compiler does not support accessing a struct field x.f where x is of type parameter type even if all types in the type parameter's type set have a field f. We may remove this restriction in Go 1.19.
You could for example add a DateStart() time.Time
method to each of the structs that returns the DATE_START field, and then use that method as part of your type constraint if you wanted to use generics.
That said, you don't need generics for this specific problem. Even without generics, you could define an interface:
type SomeInterface interface {
DateStart() time.Time
}
and then sort:
items := []SomeInterface{
INVENTORY_TAG{...},
INVENTORY_TAG{...},
}
sort.Slice(items, func(i, j int) bool { return items[i].DateStart().Before(items[j].DateStart()) })
CodePudding user response:
Like @thepudds says in this case is better use a interface implementation, but if you want try generics you could do:
package main
type JOURNAL_TAG struct {
DATE_START time.Time
DATE_END time.Time
ENTRY_NUMBER uint
VALUE float64
}
type INVENTORY_TAG struct {
DATE_START time.Time
DATE_END time.Time
PRICE float64
QUANTITY float64
ACCOUNT_NAME string
}
type hasDateInterface interface {
DateStart() time.Time
}
func (j JOURNAL_TAG) DateStart(){
return j.DATE_START
}
func (i INVENTORY_TAG) DateStart(){
return i.DATE_START
}
func sort_by_time[t hasDateInterface](slice []t, is_ascending bool) {
sort.Slice(slice, func(i, j int) bool {
return slice[i].DATE_START.After(slice[j].DateStart()) == is_ascending
})
}