получение reflect.Value(

#go #pointers #reflection

#Вперед #указатели #отражение

Вопрос:

название вопроса в значительной степени подводит итог. Я играю с отражениями, используя Go, и пытаюсь получить адрес того, на что указывает reflect.Value() .

почему?

У меня есть функция, которая может получать структуру двумя способами: первый.. это структура

 type UserInfo struct {
    Name   string        `json:"name"`
    Roles  *[]model.Role `json:"role"`
    UserId int           `json:"user_id" db:"id"`
}
  

один:

 var userInfo types.UserInfo
myFunc(amp;userInfo)
  

с этим методом у меня все хорошо, поскольку, поскольку это указатель на структуру, для которой выделена память

2-й метод:

 var userInfo *types.UserInfo
myFunc(userInfo)
  

так что здесь, если я это сделаю reflect.Value() , это нулевой указатель.
я хочу выделить эту структуру и указать userInfo на новое место.
теперь я могу легко это сделать, если я также вставлю amp;userInfo
и выполню:

 myFunc(dst interface{}, dstAddr interface{})
{
 v := reflect.ValueOf(dstAddr)
 t := reflect.TypeOf(dst)
 ptr := reflect.New(t.Type())
 ...
 v.Elem().Set(ptr)
}
  

теперь я бы исключил, что reflect.ValueOf(dst).Addr() это будет то же reflect.ValueOf(amp;dst) самое, что и на самом деле reflect.ValueOf(dst).CanAddr() возвращает false.

итак .. есть ли способ получить reflect.ValueOf(amp;dst) , имея только reflect.ValueOf(dst) ?

Комментарии:

1. Вы не можете получить reflect.Value(amp;foo) from reflect.Value(foo) , foo переданный вами файл будет копией, и вы можете получить только адрес копии, а не адрес оригинала.

2. @icza — чего я пытаюсь добиться, так это получить только один параметр. и если я отправляю только reflect.Value(amp;foo), reflect.Value(amp;foo) . Elem() должно быть Reflect.Value (foo) правильно?

3. Да, это правильно.

Ответ №1:

Независимо от того, что вы передаете reflect.ValueOf() или любой другой функции, будет сделана копия.

При этом, как говорится, reflect.Value(foo) невозможно вернуть вам адрес оригинала foo , он может вернуть вам только адрес копии. Чтобы избежать дальнейшей путаницы, в этом случае Value.CanAddr() будет возвращено false сообщение о том, что адрес, который может быть возвращен с помощью Value.Addr() , не будет тем, что большинство ожидало бы, это не был бы полезный адрес.

Как вы указали, вы хотите передать одно значение, поэтому передайте amp;foo . Делая это, вы сможете получить foo значение, указанное с amp;foo помощью Value.Elem() .

Также обратите внимание, что (обернутое) foo значение, которое вы получаете, Value.Elem() будет адресуемым, поскольку оно было получено из reflect.Value упаковки amp;foo . Так что, если reflect.Value это не reflect.ValueOf(foo) так, но reflect.ValueOf(amp;foo).Elem() вы можете вернуться (к) amp;foo .

Смотрите этот пример:

 func main() {
    var foo = 3

    fmt.Println("Address:", amp;foo)
    bar(amp;foo)
    fmt.Println("After:", foo)
}

func bar(x interface{}) {
    v := reflect.ValueOf(x)

    v2 := v.Elem()
    fmt.Println("Passed pointed value:", v2.Interface())
    v2.Set(reflect.ValueOf(4))

    fmt.Println("Address got from pointed value:", v2.Addr())
}
  

Это приведет к выводу (попробуйте это на игровой площадке Go):

 Address: 0xc000080010
Passed pointed value: 3
Address got from pointed value: 0xc000080010
After: 4