Невозможно использовать переменную golang generics в вызове функции

Я пытаюсь понять реализацию дженериков в go1.18. В моем тестовом примере я сохраняю серию тестов и пытаюсь вызвать функциональную переменную. К сожалению, я получаю сообщение об ошибке в функции EvalCases, когда пытаюсь использовать переменную tc.input, я получаю следующую ошибку:

cannot use input (variable of type T constrained by Inputer) as type string in argument to fn

Почему я получаю эту ошибку и как ее исправить?


import (
    "fmt"
    "strconv"
)

type BoolCase func(string) bool

type Inputer interface {
    int | float64 | ~string
}

type Wanter interface {
    Inputer | bool
}

type TestCase[T Inputer, U Wanter] struct {
    input T
    want  U
}

type TestConditions[T Inputer, U Wanter] map[string]TestCase[T, U]

// IsNumeric validates that a string is either a valid int64 or float64
func IsNumeric(s string) bool {
    _, err := strconv.ParseFloat(s, 64)
    return err == nil
}

func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase) {

    for name, tc := range cases {
        input := T(tc.input)
        want := tc.want
        
        // Error: cannot use input (variable of type T constrained by Inputer) as type string in argument to fn
        got := fn(input)
        fmt.Printf("name: %-20s | input: %-10v | want: %-10v | got: %v\n", name, input, want, got)
    }
}

func main() {

    var cases = TestConditions[string, bool]{
        "empty":   {input: "", want: false},
        "integer": {input: "123", want: true},
        "float":   {input: "123.456", want: true},
    }
    fn := IsNumeric
    EvalCases(cases, fn)

}

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

Ответы 1

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

Why am I receiving that error

Поскольку fn — это BoolFunc, который является func(string) bool, поэтому в качестве параметра требуется string, но input имеет тип T. Кроме того, согласно вашему определению, T удовлетворяет ограничению Inputer и, таким образом, может также принимать тип int, float64 или любой другой не-string тип, который имеет string в качестве базового типа (~string), ни один из которых неявно не приводится к string.

how do I fix it?

Вам нужно изменить определение BoolCase, чтобы оно имело параметр общего типа для одного параметра. Вы можете ограничить его Inputer, но вы также можете использовать any (interface{}).

type BoolCase[T any] func(T) bool

Затем обязательно укажите этот параметр универсального типа в сигнатуре функции EvalCases:

func EvalCases[T Inputer, U Wanter](cases TestConditions[T, U], fn BoolCase[T])

https://go.dev/play/p/RdjQXJ0WpDh

ни один из которых неявно не приводится к строке — если под приведением вы подразумеваете преобразование, обратите внимание, что в этом объединении только float64 не преобразуется в string
blackgreen 19.03.2022 19:08

@Zyl, я предполагал, что реализация тип BoolCase[T любой] func(T) bool приведет к тому, что мне придется реструктурировать функцию числовой? Почему бы мне не сделать это, чтобы удовлетворить интерфейс?

cruzan 19.03.2022 20:26

Как будет выглядеть реструктурированная функция? string удовлетворяет Inputer; это только обратное, что не обязательно верно. Обычно типизированные значения будут принимать конкретные типы во время выполнения, но во время компиляции ваши T и U не будут обрабатываться по-разному. Обратите внимание, что не все языки делают это так. C++, например, требует выяснить все потенциальные типы T во время компиляции, чтобы затем выяснить, может ли код работать. Например. код, использующий оператор + для значений T, обычно компилируется нормально, если вы не передаете нечисловой тип. Попробуйте поиграть с reflect.TypeOf().

Zyl 20.03.2022 12:24

@zyl Спасибо за объяснение.

cruzan 21.03.2022 20:51

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