Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it possible to set a value in a slice using reflection?

Tags:

reflection

go

According to The Laws of Reflection it is not possible to set the value of an element as follows, you need to use its address.

This will not work:

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

This will work:

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

So why will the following work when using slices?

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

Surely v.Index(0) is taking the value instead of address from slice floats, thus meaning it shouldn't be settable like the first example.

like image 993
Dan Avatar asked Mar 20 '23 04:03

Dan


1 Answers

In your first example, you pass the actual x. This will copy x and give it to reflect.ValueOf. When you try to do v.SetFloat, as it get only a copy, it has no way to change the original x variable.

In your second example, you pass the address of x, so you can access the original variable by dereferencing it.

In the third example, you pass floats to reflect.ValueOf, which is a slice. "Slice hold references to the underlying array" (http://golang.org/doc/effective_go.html#slices). Which mean that through the slice, you actually have a reference to the underlying object. You won't be able to change the slice itself (append & co) but you can change what the slice refers to.

like image 95
creack Avatar answered Apr 06 '23 22:04

creack