Go Reflection Panic: вызов с использованием интерфейса {} в качестве типа

Я возился с отражением в Го и наткнулся на интересный сценарий. call1() работает (возвращается "hello!") в то время как call2() паникует с reflect: Call using interface {} as type string,

В приведенном ниже коде единственная разница между call1() а также call2() я показываю inValue создан и инициализирован. Я ясно вижу почему call1() результаты в inValue быть string, в то время как call2() результаты в inValue быть interface, поэтому мой вопрос не столько в том, почему мой код производит это, а скорее:

Почему Go не может выполнить вызов функции во втором случае? Я думал, что интерфейс все еще содержит всю необходимую информацию для успешного вызова метода, учитывая, что xCopy все еще действительно представляет строку внизу. (Да, я уже читал законы отражения)

Отмечу, что из-за того, над чем я работаю, мне нужно inValue быть устанавливаемым внутри функции (отсюда использование указателей).

Спасибо!

func main() {
    fmt.Println(call1(foo, "hello"))
    fmt.Println(call2(foo, "hello"))
}

func foo(x string) string {
    return x + "!"
}

func call1(f, x interface{}) interface{} {
    fValue := reflect.ValueOf(f)
    inValue := reflect.New(reflect.TypeOf(x)).Elem()
    inValue.Set(reflect.ValueOf(x))

    inValue.Set(fValue.Call([]reflect.Value{inValue})[0])

    return inValue.Interface()
}

func call2(f, x interface{}) interface{} {
    fValue := reflect.ValueOf(f)
    xCopy := x
    inValue := reflect.ValueOf(&xCopy).Elem()

    inValue.Set(fValue.Call([]reflect.Value{inValue})[0])

    return inValue.Interface()
}

редактировать

Возможно, тогда возникает вопрос: почему Go не назначает реальный тип, а не interface, за inValue := reflect.ValueOf(&xCopy).Elem()?

1 ответ

Решение

Сообщение о панике объясняет проблему. Значение в reflect.ValueOf(&xCopy) имеет тип *interface{}, Elem() это значение имеет тип interface{}, Аргумент функции имеет тип string, interface{} значение не string значение, даже когда interface{} содержит string,

Обратите внимание, что адрес значения интерфейса является указателем на интерфейс, а не указателем на значение в интерфейсе.

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