Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/ant/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Reflection 戈朗反思。价值行为_Reflection_Go - Fatal编程技术网

Reflection 戈朗反思。价值行为

Reflection 戈朗反思。价值行为,reflection,go,Reflection,Go,我现在对golangs reflect软件包的行为感到绝望,这在我看来根本不一致 1) 据我所知,reflect.Value似乎带有指向底层值的指针。 如果我打电话 var s string v1 := reflect.ValueOf(&s).Elem() v2 := v1 v2.SetString("Hello World!") fmt.Println(s) 它给我打印“你好,世界!”。 但是,对于通过调用Field()获得的reflect.Value,这似乎不成立 这张照片 [So

我现在对golangs reflect软件包的行为感到绝望,这在我看来根本不一致

1) 据我所知,reflect.Value似乎带有指向底层值的指针。 如果我打电话

var s string
v1 := reflect.ValueOf(&s).Elem()
v2 := v1
v2.SetString("Hello World!")
fmt.Println(s)
它给我打印“你好,世界!”。 但是,对于通过调用Field()获得的reflect.Value,这似乎不成立

这张照片

[Some_value_of_type_KEY]
[]
这是一个很大的烦恼。有人知道为什么会这样吗

===================================================

2)考虑函数

func Test(v interface{}) {
    val := reflect.ValueOf(v)
    if val.Kind() != reflect.Struct {
        fmt.Println("It is a struct")
    }
}
如果我用任何结构作为参数调用它,它会打印“thisastruct”。 但是,我无法使用val为v中的内容分配新值, 由于该值不可寻址。通过以下方式解决问题:

func Test(v interface{}) {
    val := reflect.ValueOf(&v).Elem()
    if val.Kind() != reflect.Struct {
        fmt.Println("This never get's printed!")
    }
}
根据文档,我假设,通过使用“&”,我使用了一个指向v的指针,通过调用Elem()我得到了它指向的元素,因此val.Kind()应该仍然返回相同的内容。没有。val.Kind()现在是一个reflect.Interface

有没有办法不必走

valForTestingKind := reflect.ValueOf(v)
valForSettingNewValue := reflect.ValueOf(&v).Elem()

我想谈谈你的第二段代码:

val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
在第三行,您将为变量
nextval
重新分配一个新的、不同的对象。你不应该在nextval上调用某种设置方法而不是重新分配它吗?在第一个示例中,您调用了
SetString
,但在本示例中,您只是重新分配了变量,这可能就是行为不同的原因。重新分配变量后,
nextval
将不再以任何方式连接到
val.Field(0)
。还有,什么是
索引


如果这不能解释您的问题,请编辑问题以包含一个简短、自包含、正确、可编译的示例()。我希望能够将其发布到golang.org首页的文本框中,以查看问题。如果可能,您应该始终发布SSCCE。

我想谈谈您的第二段代码:

val := ... //Assign a reflect.Value to it
nextval := val.Field(0) //Make sure that Field exists and is of type map
nextval = reflect.MakeMap(reflect.MapOf(KEY, ELEM))
nextval.SetMapIndex(Some_value_of_type_KEY, Something_of_type_ELEM)
fmt.Println(nextval.MapKeys()
fmt.Println(val.Field(index).MapKeys())
在第三行,您将为变量
nextval
重新分配一个新的、不同的对象。你不应该在nextval上调用某种设置方法而不是重新分配它吗?在第一个示例中,您调用了
SetString
,但在本示例中,您只是重新分配了变量,这可能就是行为不同的原因。重新分配变量后,
nextval
将不再以任何方式连接到
val.Field(0)
。还有,什么是
索引


如果这不能解释您的问题,请编辑问题以包含一个简短、自包含、正确、可编译的示例()。我希望能够将其发布到golang.org首页的文本框中,以查看问题。如果可能,您应该始终发布SSCCE。

您尚未显示完整的可编译代码。是传递指向结构的指针,还是按值传递结构?在后一种情况下,反射无法对其进行变异。

您尚未显示完整的可编译代码。是传递指向结构的指针,还是按值传递结构?在后一种情况下,反射不能改变它。

第1部分:

通过分配给
nextval
,您正在断开它与原始
val
的关联。相反,请使用
Set()
方法

nextval.Set(reflect.MakeMap(reflect.MapOf(KEY, ELEM)))
Set()
相当于反射世界中的赋值。当然,您必须像在第一个代码示例中那样,使用
reflect.ValueOf(&v).Elem()
确保它是可分配的


第2部分:

这里的问题是你有另一个间接层次
v
是接口{}类型,并且有一个具体值,其类型是类结构。就像每个接受接口类型参数的函数一样,当调用
reflect.ValueOf
时,参数会自动转换为该类型。但是,将一个接口转换为另一个接口会导致在新接口类型中重新固定具体值。重新定位之前类型的信息丢失。例如,接受io.Writer的函数不会知道调用函数将其视为io.ReaderWriter

在这个上下文中,这意味着reflect.ValueOf无法判断您是传递了os.File(某个结构)还是在接口{}中装箱的文件。它假定您传递了一个os.文件,并向您显示“struct”类型

但是,当您传递指向接口{}的指针时,您传递的是一个可以修改的接口{}变量。您没有传递底层的具体类型,这会产生重要的后果。您可以
.Set()
任何内容,而不仅仅是原始具体类型允许的内容。您也不能编辑单个字段,因为接口{}中的任何内容都是不可分配的。如果具体类型实际上是指针,则可以执行第四次取消引用(
.Elem()
)并从中修改字段

那么,这在代码方面意味着什么

//let v = an interface{} with a concrete type of SomeStruct
val := reflect.ValueOf(&v).Elem()
fmt.Println(val.Elem().Kind())                // struct
val.Elem().Field(0).Set(10)                   // PANIC! Field isn't assignable.
val.Set("a string which is not a SomeStruct")
fmt.Println(val.Elem().Kind())                // string
我在这里举了一个例子:

第1部分:

通过分配给
nextval
,您正在断开它与原始
val
的关联。相反,请使用
Set()
方法

nextval.Set(reflect.MakeMap(reflect.MapOf(KEY, ELEM)))
Set()
相当于反射世界中的赋值。当然,您必须像在第一个代码示例中那样,使用
reflect.ValueOf(&v).Elem()
确保它是可分配的


第2部分:

这里的问题是你有另一个间接层次
v
是接口{}类型,并且有一个具体值,其类型是类结构。就像每个接受接口类型参数的函数一样,当调用
reflect.ValueOf
时,参数会自动转换为该类型。但是,将一个接口转换为另一个接口会导致在新接口类型中重新固定具体值。重新定位之前类型的信息