Как получить доступ к общему полю в структурах в дженериках в Go 1.18? Я получаю сообщение об ошибке "тип t не имеет поля или метода DATE_START"

У меня есть две структуры, которые имеют одни и те же имена и типы полей:

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.

Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
3
0
315
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Из Примечания к выпуску 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
    })
}

пытался https://go.dev/play/p/Xak4uzCNhE-

Другие вопросы по теме