为什么可以使用反射在切片中设置值?

时间:2014-06-26 21:56:58

标签: reflection go

根据The Laws of Reflection,无法按如下方式设置元素的值,您需要使用其地址。

这不起作用:

var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.

这将有效:

var x float64 = 3.4
p := reflect.ValueOf(&x) // Note: take the address of x.
p.Elem().SetFloat(7.1)

那么为什么使用切片时会有以下工作呢?

floats := []float64{3}

v := reflect.ValueOf(floats)
e := v.Index(0)
e.SetFloat(6)
fmt.Println(floats) // prints [6]

http://play.golang.org/p/BWLuq-3m85

肯定v.Index(0)正在取而不是来自切片floats的地址,因此意味着它不应像第一个示例那样设置。

1 个答案:

答案 0 :(得分:7)

在第一个示例中,您传递了实际的x。这将复制x并将其提供给reflect.ValueOf。当您尝试执行v.SetFloat时,由于它只获得副本,因此无法更改原始x变量。

在第二个示例中,您传递了x的地址,因此您可以通过取消引用来访问原始变量。

在第三个示例中,您将floats传递给reflect.ValueOf,这是一个切片。 “Slice保持对底层数组的引用”(http://golang.org/doc/effective_go.html#slices)。这意味着通过切片,您实际上有一个对底层对象的引用。您将无法更改切片本身(append& co),但可以更改切片所指的内容。