mirror of
https://github.com/golang/go
synced 2024-11-19 04:04:47 -07:00
7a70c382be
reflect.Values may point to tagged objects with interface type, e.g. x := reflect.ValueOf(new(interface{})).Elem(). We failed to consider this when implementing Elem. Also, (reflect.Value).Interface() must do one "unboxing" when it encounters such tagged objects. i.e., x.Elem().Interface() and x.Interface() are equivalent in that case. Also: - add example of tagged object with interface type. - untabify (Label).String docstring. - added tests. R=crawshaw CC=golang-dev https://golang.org/cl/18020044
192 lines
5.5 KiB
Go
192 lines
5.5 KiB
Go
// +build ignore
|
|
|
|
package main
|
|
|
|
// Test of arrays & slices with reflection.
|
|
|
|
import "reflect"
|
|
|
|
var a, b int
|
|
|
|
type S string
|
|
|
|
func reflectValueSlice() {
|
|
// reflect.Value contains a slice.
|
|
slice := make([]*int, 10) // @line slice
|
|
slice[0] = &a
|
|
rvsl := reflect.ValueOf(slice).Slice(0, 0)
|
|
print(rvsl.Interface()) // @types []*int
|
|
print(rvsl.Interface().([]*int)) // @pointsto makeslice@slice:15
|
|
print(rvsl.Interface().([]*int)[42]) // @pointsto main.a
|
|
|
|
// reflect.Value contains an arrayay (non-addressable).
|
|
array := [10]*int{&a} // @line array
|
|
rvarray := reflect.ValueOf(array).Slice(0, 0)
|
|
print(rvarray.Interface()) // @types
|
|
print(rvarray.Interface().([]*int)) // @pointsto
|
|
print(rvarray.Interface().([]*int)[42]) // @pointsto
|
|
|
|
// reflect.Value contains a pointer-to-array
|
|
rvparray := reflect.ValueOf(&array).Slice(0, 0)
|
|
print(rvparray.Interface()) // @types []*int
|
|
print(rvparray.Interface().([]*int)) // @pointsto array@array:2
|
|
print(rvparray.Interface().([]*int)[42]) // @pointsto main.a
|
|
|
|
// reflect.Value contains a string.
|
|
rvstring := reflect.ValueOf("hi").Slice(0, 0)
|
|
print(rvstring.Interface()) // @types string
|
|
|
|
// reflect.Value contains a (named) string type.
|
|
rvS := reflect.ValueOf(S("hi")).Slice(0, 0)
|
|
print(rvS.Interface()) // @types S
|
|
|
|
// reflect.Value contains a non-array pointer.
|
|
rvptr := reflect.ValueOf(new(int)).Slice(0, 0)
|
|
print(rvptr.Interface()) // @types
|
|
|
|
// reflect.Value contains a non-string basic type.
|
|
rvint := reflect.ValueOf(3).Slice(0, 0)
|
|
print(rvint.Interface()) // @types
|
|
}
|
|
|
|
func reflectValueBytes() {
|
|
sl1 := make([]byte, 0) // @line ar5sl1
|
|
sl2 := make([]byte, 0) // @line ar5sl2
|
|
|
|
rvsl1 := reflect.ValueOf(sl1)
|
|
print(rvsl1.Interface()) // @types []byte
|
|
print(rvsl1.Interface().([]byte)) // @pointsto makeslice@ar5sl1:13
|
|
print(rvsl1.Bytes()) // @pointsto makeslice@ar5sl1:13
|
|
|
|
rvsl2 := reflect.ValueOf(123)
|
|
rvsl2.SetBytes(sl2)
|
|
print(rvsl2.Interface()) // @types int
|
|
print(rvsl2.Interface().([]byte)) // @pointsto
|
|
print(rvsl2.Bytes()) // @pointsto
|
|
|
|
rvsl3 := reflect.ValueOf([]byte(nil))
|
|
rvsl3.SetBytes(sl2)
|
|
print(rvsl3.Interface()) // @types []byte
|
|
print(rvsl3.Interface().([]byte)) // @pointsto makeslice@ar5sl2:13
|
|
print(rvsl3.Bytes()) // @pointsto makeslice@ar5sl2:13
|
|
}
|
|
|
|
func reflectValueIndex() {
|
|
slice := []*int{&a} // @line ar6slice
|
|
rv1 := reflect.ValueOf(slice)
|
|
print(rv1.Index(42).Interface()) // @types *int
|
|
print(rv1.Index(42).Interface().(*int)) // @pointsto main.a
|
|
|
|
array := [10]*int{&a}
|
|
rv2 := reflect.ValueOf(array)
|
|
print(rv2.Index(42).Interface()) // @types *int
|
|
print(rv2.Index(42).Interface().(*int)) // @pointsto main.a
|
|
|
|
rv3 := reflect.ValueOf("string")
|
|
print(rv3.Index(42).Interface()) // @types rune
|
|
|
|
rv4 := reflect.ValueOf(&array)
|
|
print(rv4.Index(42).Interface()) // @types
|
|
|
|
rv5 := reflect.ValueOf(3)
|
|
print(rv5.Index(42).Interface()) // @types
|
|
}
|
|
|
|
func reflectValueElem() {
|
|
// Interface.
|
|
var iface interface{} = &a
|
|
rv1 := reflect.ValueOf(&iface).Elem()
|
|
print(rv1.Interface()) // @types *int
|
|
print(rv1.Interface().(*int)) // @pointsto main.a
|
|
print(rv1.Elem().Interface()) // @types *int
|
|
print(rv1.Elem().Interface().(*int)) // @pointsto main.a
|
|
|
|
print(reflect.ValueOf(new(interface{})).Elem().Elem()) // @types
|
|
|
|
// Pointer.
|
|
ptr := &a
|
|
rv2 := reflect.ValueOf(&ptr)
|
|
print(rv2.Elem().Interface()) // @types *int
|
|
print(rv2.Elem().Interface().(*int)) // @pointsto main.a
|
|
|
|
// No other type works with (rV).Elem, not even those that
|
|
// work with (rT).Elem: slice, array, map, chan.
|
|
|
|
rv3 := reflect.ValueOf([]*int{&a})
|
|
print(rv3.Elem().Interface()) // @types
|
|
|
|
rv4 := reflect.ValueOf([10]*int{&a})
|
|
print(rv4.Elem().Interface()) // @types
|
|
|
|
rv5 := reflect.ValueOf(map[*int]*int{&a: &b})
|
|
print(rv5.Elem().Interface()) // @types
|
|
|
|
ch := make(chan *int)
|
|
ch <- &a
|
|
rv6 := reflect.ValueOf(ch)
|
|
print(rv6.Elem().Interface()) // @types
|
|
|
|
rv7 := reflect.ValueOf(3)
|
|
print(rv7.Elem().Interface()) // @types
|
|
}
|
|
|
|
func reflectTypeElem() {
|
|
rt1 := reflect.TypeOf(make([]*int, 0))
|
|
print(reflect.Zero(rt1.Elem())) // @types *int
|
|
|
|
rt2 := reflect.TypeOf([10]*int{})
|
|
print(reflect.Zero(rt2.Elem())) // @types *int
|
|
|
|
rt3 := reflect.TypeOf(map[*int]*int{})
|
|
print(reflect.Zero(rt3.Elem())) // @types *int
|
|
|
|
rt4 := reflect.TypeOf(make(chan *int))
|
|
print(reflect.Zero(rt4.Elem())) // @types *int
|
|
|
|
ptr := &a
|
|
rt5 := reflect.TypeOf(&ptr)
|
|
print(reflect.Zero(rt5.Elem())) // @types *int
|
|
|
|
rt6 := reflect.TypeOf(3)
|
|
print(reflect.Zero(rt6.Elem())) // @types
|
|
}
|
|
|
|
func reflectPtrTo() {
|
|
tInt := reflect.TypeOf(3)
|
|
tPtrInt := reflect.PtrTo(tInt)
|
|
print(reflect.Zero(tPtrInt)) // @types *int
|
|
tPtrPtrInt := reflect.PtrTo(tPtrInt)
|
|
print(reflect.Zero(tPtrPtrInt)) // @types **int
|
|
}
|
|
|
|
func reflectSliceOf() {
|
|
tInt := reflect.TypeOf(3)
|
|
tSliceInt := reflect.SliceOf(tInt)
|
|
print(reflect.Zero(tSliceInt)) // @types []int
|
|
}
|
|
|
|
type T struct{ x int }
|
|
|
|
func reflectMakeSlice() {
|
|
rt := []reflect.Type{
|
|
reflect.TypeOf(3),
|
|
reflect.TypeOf([]int{}),
|
|
reflect.TypeOf([]T{}),
|
|
}[0]
|
|
sl := reflect.MakeSlice(rt, 0, 0)
|
|
print(sl) // @types []int | []T
|
|
print(sl) // @pointsto <alloc in reflect.MakeSlice> | <alloc in reflect.MakeSlice>
|
|
print(&sl.Interface().([]T)[0].x) // @pointsto <alloc in reflect.MakeSlice>[*].x
|
|
}
|
|
|
|
func main() {
|
|
reflectValueSlice()
|
|
reflectValueBytes()
|
|
reflectValueIndex()
|
|
reflectValueElem()
|
|
reflectTypeElem()
|
|
reflectPtrTo()
|
|
reflectSliceOf()
|
|
reflectMakeSlice()
|
|
}
|