【问题标题】:getting reflect.Value(&foo) from reflect.Value(foo)从 reflect.Value(foo) 获取 reflect.Value(&foo)
【发布时间】:2021-01-21 00:16:02
【问题描述】:

问题的标题几乎概括了它。我正在使用 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(&userInfo)

使用这种方法我很好,因为它是一个指向已分配内存的结构的指针

第二种方法:

var userInfo *types.UserInfo
myFunc(userInfo)

所以如果我这样做 reflect.Value() 这是一个零指针。 我想分配该结构并将 userInfo 指向新位置。 现在我可以很容易地做到这一点,如果我也粘贴 &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(&dst) 相同,但实际上 reflect.ValueOf(dst).CanAddr() 返回 false。

所以.. 有没有办法获得reflect.ValueOf(&dst) 而只有reflect.ValueOf(dst)

【问题讨论】:

  • 你不能从reflect.Value(foo)得到reflect.Value(&foo),你传递的foo是一个副本,你只能得到副本的地址,不能得到原的地址。
  • @icza - 我想要实现的是只获得一个参数。如果我只发送 reflect.Value(&foo),那么 reflect.Value(&foo).Elem() 应该是 Reflect.Value(foo) 正确的?
  • 是的,没错。

标签: go pointers reflection


【解决方案1】:

无论您传递给reflect.ValueOf() 或任何其他函数,都会生成一个副本。

话虽如此,reflect.Value(foo)不可能把原来的foo的地址给你,它只能给你复制的地址。为避免进一步混淆,在这种情况下Value.CanAddr() 将返回false,让您知道可以 使用Value.Addr() 返回的地址不是大多数人所期望的,它不会是一个有用的地址。

正如你所指出的,你想传递一个 single 值,所以传递&foo。这样做您将能够使用Value.Elem() 获得&foo 指向的foo 值。

还请注意,您通过Value.Elem() 获得的(包装的)foo 值将是可寻址的,因为它是从包装&fooreflect.Value 获得的。因此,如果reflect.Value不是 reflect.ValueOf(foo) 而是reflect.ValueOf(&foo).Elem(),您可以返回(到)&foo

看这个例子:

func main() {
    var foo = 3

    fmt.Println("Address:", &foo)
    bar(&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 Playground 上尝试):

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

【讨论】:

    猜你喜欢
    • 2017-07-26
    • 2018-06-14
    • 2013-08-08
    • 2014-02-22
    • 2015-11-18
    • 1970-01-01
    • 2015-12-29
    • 1970-01-01
    • 2022-09-04
    相关资源
    最近更新 更多