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
,
Обратите внимание, что адрес значения интерфейса является указателем на интерфейс, а не указателем на значение в интерфейсе.