Получить указатель на переменную, полученную через интерфейс - PullRequest
0 голосов
/ 08 февраля 2019

В следующем коде

var a int
var b interface{}

b = a

fmt.Printf("%T, %T \n", a, &a)
fmt.Printf("%T, %T \n", b, &b)

output:

int, *int 
int, *interface {}

Я ожидаю, что тип & b будет указателем на int.

У меня есть двавопросы:

1) Почему указатель на интерфейс {}?

2) Как я могу получить указатель на исходный тип?

Ответы [ 2 ]

0 голосов
/ 08 февраля 2019

Просто для завершения ответ icza .Если вы не знаете тип значения, хранящегося в интерфейсе (и, следовательно, вы не можете явно использовать утверждение типа), вы можете использовать отражение пакет:

var a int
var b interface{}
b = &a
fmt.Println(reflect.TypeOf(b))
0 голосов
/ 08 февраля 2019

&b => это адресный оператор , примененный к переменной b, тип которой interface{}.Таким образом, &b будет указателем типа *interface{}, указывающим на переменную b.Если вы берете адрес переменной типа T, результат всегда будет иметь тип *T.

Вы не можете получить адрес переменной a из b, потому что присваивание:

b = a

Просто копирует значение a в b.Он оборачивает значение a в значение интерфейса типа interface{} и сохраняет это значение интерфейса в b.Это значение полностью отделено от a.

Как правило, все назначения копируют назначенные значения.В Go нет ссылочных типов.Самое близкое, что вы можете получить к тому, что вы хотите, это если вы сначала сохраните адрес a в b, например:

b = &a

Тогда вы можете использовать утверждение типа чтобы получить a адрес из b, например:

fmt.Printf("%T, %T \n", a, &a)
fmt.Printf("%T, %T \n", b, b.(*int))

Это выводит (попробуйте на Go Playground ):

int, *int
*int, *int

(Примечание: когда вы просто печатаете b, поскольку он относится к типу интерфейса, пакет fmt печатает (конкретное) значение, заключенное в нем.)

См. Связанные вопросы:

Как получить указатель на переменную, которая маскируется как интерфейс?

Изменение типа и значения указателя в интерфейсе с отражением

...