У меня есть две структуры, которые имеют одни и те же имена и типы полей:
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
}
и у меня есть функция, которая обращается к общему полю DATE_START
, которое должно сортировать слайсы этих типов:
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
})
}
Запуск go build
сообщает об ошибке компилятора:
slice[i].DATE_START undefined (type t has no field or method DATE_START)
Я хочу отсортировать срезы этих двух типов с помощью дженериков, возможно ли это?
Я использую Go 1.18.
Из Примечания к выпуску Go 1.18:
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.
Например, вы можете добавить метод DateStart() time.Time
к каждой из структур, возвращающих поле DATE_START, а затем использовать этот метод как часть вашего ограничение типа, если вы хотите использовать дженерики.
Тем не менее, вам не нужны дженерики для этой конкретной проблемы. Даже без дженериков вы можете определить интерфейс:
type SomeInterface interface {
DateStart() time.Time
}
а затем сортировать:
items := []SomeInterface{
INVENTORY_TAG{...},
INVENTORY_TAG{...},
}
sort.Slice(items, func(i, j int) bool { return items[i].DateStart().Before(items[j].DateStart()) })
Как говорит @thepudds, в этом случае лучше использовать реализацию интерфейса, но если вы хотите попробовать дженерики, вы можете сделать:
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
})
}