#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)
fromreflect.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