2008-10-23 18:13:34 -06:00
|
|
|
// Copyright 2009 The Go Authors. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
|
|
|
|
2009-08-12 14:18:37 -06:00
|
|
|
package reflect_test
|
2008-10-23 18:13:34 -06:00
|
|
|
|
|
|
|
import (
|
2011-04-20 14:24:45 -06:00
|
|
|
"bytes"
|
2011-08-21 21:22:42 -06:00
|
|
|
"encoding/base64"
|
2012-09-22 06:52:27 -06:00
|
|
|
"flag"
|
2010-06-14 12:23:11 -06:00
|
|
|
"fmt"
|
2009-12-15 16:40:16 -07:00
|
|
|
"io"
|
2012-09-18 12:22:41 -06:00
|
|
|
"math/rand"
|
2009-12-15 16:40:16 -07:00
|
|
|
"os"
|
|
|
|
. "reflect"
|
2013-03-06 16:52:32 -07:00
|
|
|
"runtime"
|
2013-03-26 12:50:29 -06:00
|
|
|
"sort"
|
2012-09-18 12:22:41 -06:00
|
|
|
"sync"
|
2009-12-15 16:40:16 -07:00
|
|
|
"testing"
|
2012-09-18 12:22:41 -06:00
|
|
|
"time"
|
2009-12-15 16:40:16 -07:00
|
|
|
"unsafe"
|
2008-10-23 18:13:34 -06:00
|
|
|
)
|
|
|
|
|
2011-11-16 17:18:25 -07:00
|
|
|
func TestBool(t *testing.T) {
|
|
|
|
v := ValueOf(true)
|
|
|
|
if v.Bool() != true {
|
|
|
|
t.Fatal("ValueOf(true).Bool() = false")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-07 12:03:12 -06:00
|
|
|
type integer int
|
2009-11-05 15:23:20 -07:00
|
|
|
type T struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int
|
|
|
|
b float64
|
|
|
|
c string
|
|
|
|
d *int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-07-07 12:03:12 -06:00
|
|
|
|
|
|
|
type pair struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
i interface{}
|
|
|
|
s string
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
2008-10-23 18:13:34 -06:00
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
func isDigit(c uint8) bool { return '0' <= c && c <= '9' }
|
2008-10-23 18:13:34 -06:00
|
|
|
|
2009-07-07 12:03:12 -06:00
|
|
|
func assert(t *testing.T, s, want string) {
|
|
|
|
if s != want {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("have %#q want %#q", s, want)
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
func typestring(i interface{}) string { return TypeOf(i).String() }
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var typeTests = []pair{
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct{ x int }{}, "int"},
|
|
|
|
{struct{ x int8 }{}, "int8"},
|
|
|
|
{struct{ x int16 }{}, "int16"},
|
|
|
|
{struct{ x int32 }{}, "int32"},
|
|
|
|
{struct{ x int64 }{}, "int64"},
|
|
|
|
{struct{ x uint }{}, "uint"},
|
|
|
|
{struct{ x uint8 }{}, "uint8"},
|
|
|
|
{struct{ x uint16 }{}, "uint16"},
|
|
|
|
{struct{ x uint32 }{}, "uint32"},
|
|
|
|
{struct{ x uint64 }{}, "uint64"},
|
|
|
|
{struct{ x float32 }{}, "float32"},
|
|
|
|
{struct{ x float64 }{}, "float64"},
|
|
|
|
{struct{ x int8 }{}, "int8"},
|
|
|
|
{struct{ x (**int8) }{}, "**int8"},
|
|
|
|
{struct{ x (**integer) }{}, "**reflect_test.integer"},
|
|
|
|
{struct{ x ([32]int32) }{}, "[32]int32"},
|
|
|
|
{struct{ x ([]int8) }{}, "[]int8"},
|
2011-12-02 12:45:07 -07:00
|
|
|
{struct{ x (map[string]int32) }{}, "map[string]int32"},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct{ x (chan<- string) }{}, "chan<- string"},
|
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
c chan *int32
|
|
|
|
d float32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { c chan *int32; d float32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct{ x (func(a int8, b int32)) }{}, "func(int8, int32)"},
|
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
c func(chan *integer, *int8)
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { c func(chan *reflect_test.integer, *int8) }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { a int8; b int32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int8
|
|
|
|
c int32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { a int8; b int8; c int32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int8
|
|
|
|
c int8
|
|
|
|
d int32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { a int8; b int8; c int8; d int32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int8
|
|
|
|
c int8
|
|
|
|
d int8
|
|
|
|
e int32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { a int8; b int8; c int8; d int8; e int32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int8
|
|
|
|
c int8
|
|
|
|
d int8
|
|
|
|
e int8
|
|
|
|
f int32
|
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
|
|
|
"struct { a int8; b int8; c int8; d int8; e int8; f int32 }",
|
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2011-06-29 07:52:34 -06:00
|
|
|
a int8 `reflect:"hi there"`
|
2009-12-15 16:40:16 -07:00
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
2011-06-29 07:52:34 -06:00
|
|
|
`struct { a int8 "reflect:\"hi there\"" }`,
|
2009-11-05 19:27:30 -07:00
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2011-06-29 07:52:34 -06:00
|
|
|
a int8 `reflect:"hi \x00there\t\n\"\\"`
|
2009-12-15 16:40:16 -07:00
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
2011-06-29 07:52:34 -06:00
|
|
|
`struct { a int8 "reflect:\"hi \\x00there\\t\\n\\\"\\\\\"" }`,
|
2009-11-05 19:27:30 -07:00
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x struct {
|
2010-06-14 12:23:11 -06:00
|
|
|
f func(args ...int)
|
2009-12-15 16:40:16 -07:00
|
|
|
}
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
2010-06-14 12:23:11 -06:00
|
|
|
"struct { f func(...int) }",
|
2009-11-05 19:27:30 -07:00
|
|
|
},
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct {
|
2009-11-05 15:23:20 -07:00
|
|
|
x (interface {
|
2010-02-24 14:24:37 -07:00
|
|
|
a(func(func(int) int) func(func(int)) int)
|
2009-12-15 16:40:16 -07:00
|
|
|
b()
|
|
|
|
})
|
2009-11-05 19:27:30 -07:00
|
|
|
}{},
|
2011-04-21 06:14:50 -06:00
|
|
|
"interface { reflect_test.a(func(func(int) int) func(func(int)) int); reflect_test.b() }",
|
2009-11-05 19:27:30 -07:00
|
|
|
},
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
var valueTests = []pair{
|
2013-08-20 22:41:55 -06:00
|
|
|
{new(int), "132"},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(int8), "8"},
|
|
|
|
{new(int16), "16"},
|
|
|
|
{new(int32), "32"},
|
|
|
|
{new(int64), "64"},
|
2013-08-20 22:41:55 -06:00
|
|
|
{new(uint), "132"},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(uint8), "8"},
|
|
|
|
{new(uint16), "16"},
|
|
|
|
{new(uint32), "32"},
|
|
|
|
{new(uint64), "64"},
|
|
|
|
{new(float32), "256.25"},
|
|
|
|
{new(float64), "512.125"},
|
2013-08-20 22:41:55 -06:00
|
|
|
{new(complex64), "532.125+10i"},
|
|
|
|
{new(complex128), "564.25+1i"},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(string), "stringy cheese"},
|
|
|
|
{new(bool), "true"},
|
|
|
|
{new(*int8), "*int8(0)"},
|
|
|
|
{new(**int8), "**int8(0)"},
|
|
|
|
{new([5]int32), "[5]int32{0, 0, 0, 0, 0}"},
|
|
|
|
{new(**integer), "**reflect_test.integer(0)"},
|
2011-12-02 12:45:07 -07:00
|
|
|
{new(map[string]int32), "map[string]int32{<can't iterate on maps>}"},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(chan<- string), "chan<- string"},
|
|
|
|
{new(func(a int8, b int32)), "func(int8, int32)(0)"},
|
|
|
|
{new(struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
c chan *int32
|
|
|
|
d float32
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
}),
|
2009-11-05 19:27:30 -07:00
|
|
|
"struct { c chan *int32; d float32 }{chan *int32, 0}",
|
|
|
|
},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(struct{ c func(chan *integer, *int8) }),
|
2009-11-05 19:27:30 -07:00
|
|
|
"struct { c func(chan *reflect_test.integer, *int8) }{func(chan *reflect_test.integer, *int8)(0)}",
|
|
|
|
},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int32
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
}),
|
2009-11-05 19:27:30 -07:00
|
|
|
"struct { a int8; b int32 }{0, 0}",
|
|
|
|
},
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
{new(struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int8
|
|
|
|
b int8
|
|
|
|
c int32
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
}),
|
2009-11-05 19:27:30 -07:00
|
|
|
"struct { a int8; b int8; c int32 }{0, 0, 0}",
|
|
|
|
},
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func testType(t *testing.T, i int, typ Type, want string) {
|
2009-12-15 16:40:16 -07:00
|
|
|
s := typ.String()
|
2009-07-07 12:03:12 -06:00
|
|
|
if s != want {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("#%d: have %#q, want %#q", i, s, want)
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTypes(t *testing.T) {
|
|
|
|
for i, tt := range typeTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
testType(t, i, ValueOf(tt.i).Field(0).Type(), tt.s)
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-21 20:51:27 -06:00
|
|
|
func TestSet(t *testing.T) {
|
2009-07-07 12:03:12 -06:00
|
|
|
for i, tt := range valueTests {
|
2011-11-16 17:18:25 -07:00
|
|
|
v := ValueOf(tt.i)
|
|
|
|
v = v.Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
switch v.Kind() {
|
|
|
|
case Int:
|
|
|
|
v.SetInt(132)
|
|
|
|
case Int8:
|
|
|
|
v.SetInt(8)
|
|
|
|
case Int16:
|
|
|
|
v.SetInt(16)
|
|
|
|
case Int32:
|
|
|
|
v.SetInt(32)
|
|
|
|
case Int64:
|
|
|
|
v.SetInt(64)
|
|
|
|
case Uint:
|
|
|
|
v.SetUint(132)
|
|
|
|
case Uint8:
|
|
|
|
v.SetUint(8)
|
|
|
|
case Uint16:
|
|
|
|
v.SetUint(16)
|
|
|
|
case Uint32:
|
|
|
|
v.SetUint(32)
|
|
|
|
case Uint64:
|
|
|
|
v.SetUint(64)
|
|
|
|
case Float32:
|
|
|
|
v.SetFloat(256.25)
|
|
|
|
case Float64:
|
|
|
|
v.SetFloat(512.125)
|
|
|
|
case Complex64:
|
|
|
|
v.SetComplex(532.125 + 10i)
|
|
|
|
case Complex128:
|
|
|
|
v.SetComplex(564.25 + 1i)
|
|
|
|
case String:
|
|
|
|
v.SetString("stringy cheese")
|
|
|
|
case Bool:
|
|
|
|
v.SetBool(true)
|
2008-10-23 18:13:34 -06:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
s := valueToString(v)
|
2009-07-07 12:03:12 -06:00
|
|
|
if s != tt.s {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
|
2008-10-23 18:13:34 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-10-21 20:51:27 -06:00
|
|
|
func TestSetValue(t *testing.T) {
|
|
|
|
for i, tt := range valueTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(tt.i).Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
switch v.Kind() {
|
|
|
|
case Int:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(int(132)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Int8:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(int8(8)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Int16:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(int16(16)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Int32:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(int32(32)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Int64:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(int64(64)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Uint:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(uint(132)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Uint8:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(uint8(8)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Uint16:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(uint16(16)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Uint32:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(uint32(32)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Uint64:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(uint64(64)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Float32:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(float32(256.25)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Float64:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(512.125))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Complex64:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(complex64(532.125 + 10i)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Complex128:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(complex128(564.25 + 1i)))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case String:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf("stringy cheese"))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
case Bool:
|
2011-04-25 11:39:16 -06:00
|
|
|
v.Set(ValueOf(true))
|
2009-10-21 20:51:27 -06:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
s := valueToString(v)
|
2009-10-21 20:51:27 -06:00
|
|
|
if s != tt.s {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("#%d: have %#q, want %#q", i, s, tt.s)
|
2009-10-21 20:51:27 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var _i = 7
|
|
|
|
|
|
|
|
var valueToStringTests = []pair{
|
2010-10-22 11:06:33 -06:00
|
|
|
{123, "123"},
|
|
|
|
{123.5, "123.5"},
|
|
|
|
{byte(123), "123"},
|
|
|
|
{"abc", "abc"},
|
|
|
|
{T{123, 456.75, "hello", &_i}, "reflect_test.T{123, 456.75, hello, *int(&7)}"},
|
|
|
|
{new(chan *T), "*chan *reflect_test.T(&chan *reflect_test.T)"},
|
|
|
|
{[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
|
|
|
|
{&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[10]int(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
|
|
|
|
{[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}"},
|
|
|
|
{&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, "*[]int(&[]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})"},
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
2008-10-23 18:13:34 -06:00
|
|
|
|
2009-07-07 12:03:12 -06:00
|
|
|
func TestValueToString(t *testing.T) {
|
|
|
|
for i, test := range valueToStringTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
s := valueToString(ValueOf(test.i))
|
2009-07-07 12:03:12 -06:00
|
|
|
if s != test.s {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("#%d: have %#q, want %#q", i, s, test.s)
|
2008-11-12 20:05:05 -07:00
|
|
|
}
|
|
|
|
}
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
2008-11-12 20:05:05 -07:00
|
|
|
|
2009-07-07 12:03:12 -06:00
|
|
|
func TestArrayElemSet(t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(&[10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}).Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v.Index(4).SetInt(123)
|
2009-12-15 16:40:16 -07:00
|
|
|
s := valueToString(v)
|
|
|
|
const want = "[10]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
|
2009-07-07 12:03:12 -06:00
|
|
|
if s != want {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("[10]int: have %#q want %#q", s, want)
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
2008-11-13 14:42:59 -07:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
v = ValueOf([]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10})
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v.Index(4).SetInt(123)
|
2009-12-15 16:40:16 -07:00
|
|
|
s = valueToString(v)
|
|
|
|
const want1 = "[]int{1, 2, 3, 4, 123, 6, 7, 8, 9, 10}"
|
2009-07-07 12:03:12 -06:00
|
|
|
if s != want1 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("[]int: have %#q want %#q", s, want1)
|
2008-11-13 14:42:59 -07:00
|
|
|
}
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestPtrPointTo(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
var ip *int32
|
|
|
|
var i int32 = 1234
|
2011-04-25 11:39:16 -06:00
|
|
|
vip := ValueOf(&ip)
|
|
|
|
vi := ValueOf(&i).Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
vip.Elem().Set(vi.Addr())
|
2009-07-07 12:03:12 -06:00
|
|
|
if *ip != 1234 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("got %d, want 1234", *ip)
|
2008-11-13 14:42:59 -07:00
|
|
|
}
|
2010-08-17 16:12:28 -06:00
|
|
|
|
|
|
|
ip = nil
|
2011-04-25 11:39:16 -06:00
|
|
|
vp := ValueOf(&ip).Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
vp.Set(Zero(vp.Type()))
|
2010-08-17 16:12:28 -06:00
|
|
|
if ip != nil {
|
|
|
|
t.Errorf("got non-nil (%p), want nil", ip)
|
|
|
|
}
|
2008-10-23 18:13:34 -06:00
|
|
|
}
|
2008-11-24 15:51:33 -07:00
|
|
|
|
2010-04-20 18:02:08 -06:00
|
|
|
func TestPtrSetNil(t *testing.T) {
|
|
|
|
var i int32 = 1234
|
|
|
|
ip := &i
|
2011-04-25 11:39:16 -06:00
|
|
|
vip := ValueOf(&ip)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
vip.Elem().Set(Zero(vip.Elem().Type()))
|
2010-04-20 18:02:08 -06:00
|
|
|
if ip != nil {
|
|
|
|
t.Errorf("got non-nil (%d), want nil", *ip)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMapSetNil(t *testing.T) {
|
|
|
|
m := make(map[string]int)
|
2011-04-25 11:39:16 -06:00
|
|
|
vm := ValueOf(&m)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
vm.Elem().Set(Zero(vm.Elem().Type()))
|
2010-04-20 18:02:08 -06:00
|
|
|
if m != nil {
|
|
|
|
t.Errorf("got non-nil (%p), want nil", m)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-11-08 22:57:59 -07:00
|
|
|
func TestAll(t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
testType(t, 1, TypeOf((int8)(0)), "int8")
|
|
|
|
testType(t, 2, TypeOf((*int8)(nil)).Elem(), "int8")
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf((*struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
c chan *int32
|
|
|
|
d float32
|
|
|
|
})(nil))
|
|
|
|
testType(t, 3, typ, "*struct { c chan *int32; d float32 }")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
etyp := typ.Elem()
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 4, etyp, "struct { c chan *int32; d float32 }")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
styp := etyp
|
2009-12-15 16:40:16 -07:00
|
|
|
f := styp.Field(0)
|
|
|
|
testType(t, 5, f.Type, "chan *int32")
|
|
|
|
|
|
|
|
f, present := styp.FieldByName("d")
|
2009-07-16 19:21:14 -06:00
|
|
|
if !present {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("FieldByName says present field is absent")
|
2009-07-16 19:21:14 -06:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 6, f.Type, "float32")
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
f, present = styp.FieldByName("absent")
|
2009-07-16 19:21:14 -06:00
|
|
|
if present {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("FieldByName says absent field is present")
|
2009-07-16 19:21:14 -06:00
|
|
|
}
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
typ = TypeOf([32]int32{})
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 7, typ, "[32]int32")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
testType(t, 8, typ.Elem(), "int32")
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
typ = TypeOf((map[string]*int32)(nil))
|
2011-12-02 12:45:07 -07:00
|
|
|
testType(t, 9, typ, "map[string]*int32")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
mtyp := typ
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 10, mtyp.Key(), "string")
|
|
|
|
testType(t, 11, mtyp.Elem(), "*int32")
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
typ = TypeOf((chan<- string)(nil))
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 12, typ, "chan<- string")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
testType(t, 13, typ.Elem(), "string")
|
2009-07-07 12:03:12 -06:00
|
|
|
|
|
|
|
// make sure tag strings are not part of element type
|
2011-04-25 11:39:16 -06:00
|
|
|
typ = TypeOf(struct {
|
2011-06-29 07:52:34 -06:00
|
|
|
d []uint32 `reflect:"TAG"`
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
}{}).Field(0).Type
|
2009-12-15 16:40:16 -07:00
|
|
|
testType(t, 14, typ, "[]uint32")
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func TestInterfaceGet(t *testing.T) {
|
2009-11-05 15:23:20 -07:00
|
|
|
var inter struct {
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
E interface{}
|
2009-12-15 16:40:16 -07:00
|
|
|
}
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
inter.E = 123.456
|
2011-04-25 11:39:16 -06:00
|
|
|
v1 := ValueOf(&inter)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v2 := v1.Elem().Field(0)
|
2011-10-31 11:09:40 -06:00
|
|
|
assert(t, v2.Type().String(), "interface {}")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
i2 := v2.Interface()
|
2011-04-25 11:39:16 -06:00
|
|
|
v3 := ValueOf(i2)
|
2011-01-19 21:09:00 -07:00
|
|
|
assert(t, v3.Type().String(), "float64")
|
2008-11-24 15:51:33 -07:00
|
|
|
}
|
2008-12-10 16:55:59 -07:00
|
|
|
|
2009-04-06 22:28:04 -06:00
|
|
|
func TestInterfaceValue(t *testing.T) {
|
2009-11-05 15:23:20 -07:00
|
|
|
var inter struct {
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
E interface{}
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
inter.E = 123.456
|
2011-04-25 11:39:16 -06:00
|
|
|
v1 := ValueOf(&inter)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v2 := v1.Elem().Field(0)
|
2011-10-31 11:09:40 -06:00
|
|
|
assert(t, v2.Type().String(), "interface {}")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v3 := v2.Elem()
|
2011-01-19 21:09:00 -07:00
|
|
|
assert(t, v3.Type().String(), "float64")
|
2009-04-15 01:55:58 -06:00
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
i3 := v2.Interface()
|
2011-01-19 21:09:00 -07:00
|
|
|
if _, ok := i3.(float64); !ok {
|
2011-04-25 11:39:16 -06:00
|
|
|
t.Error("v2.Interface() did not return float64, got ", TypeOf(i3))
|
2009-04-14 20:03:57 -06:00
|
|
|
}
|
2009-04-06 22:28:04 -06:00
|
|
|
}
|
|
|
|
|
2009-04-14 07:46:01 -06:00
|
|
|
func TestFunctionValue(t *testing.T) {
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
var x interface{} = func() {}
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(x)
|
2011-12-06 08:48:17 -07:00
|
|
|
if fmt.Sprint(v.Interface()) != fmt.Sprint(x) {
|
|
|
|
t.Fatalf("TestFunction returned wrong pointer")
|
2009-04-14 07:46:01 -06:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
assert(t, v.Type().String(), "func()")
|
2009-04-14 07:46:01 -06:00
|
|
|
}
|
|
|
|
|
2010-12-14 14:50:08 -07:00
|
|
|
var appendTests = []struct {
|
|
|
|
orig, extra []int
|
|
|
|
}{
|
|
|
|
{make([]int, 2, 4), []int{22}},
|
|
|
|
{make([]int, 2, 4), []int{22, 33, 44}},
|
|
|
|
}
|
|
|
|
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
func sameInts(x, y []int) bool {
|
|
|
|
if len(x) != len(y) {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
for i, xx := range x {
|
|
|
|
if xx != y[i] {
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2010-12-14 14:50:08 -07:00
|
|
|
func TestAppend(t *testing.T) {
|
|
|
|
for i, test := range appendTests {
|
|
|
|
origLen, extraLen := len(test.orig), len(test.extra)
|
|
|
|
want := append(test.orig, test.extra...)
|
|
|
|
// Convert extra from []int to []Value.
|
|
|
|
e0 := make([]Value, len(test.extra))
|
|
|
|
for j, e := range test.extra {
|
2011-04-25 11:39:16 -06:00
|
|
|
e0[j] = ValueOf(e)
|
2010-12-14 14:50:08 -07:00
|
|
|
}
|
|
|
|
// Convert extra from []int to *SliceValue.
|
2011-04-25 11:39:16 -06:00
|
|
|
e1 := ValueOf(test.extra)
|
2010-12-14 14:50:08 -07:00
|
|
|
// Test Append.
|
2011-04-25 11:39:16 -06:00
|
|
|
a0 := ValueOf(test.orig)
|
2010-12-14 14:50:08 -07:00
|
|
|
have0 := Append(a0, e0...).Interface().([]int)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
if !sameInts(have0, want) {
|
|
|
|
t.Errorf("Append #%d: have %v, want %v (%p %p)", i, have0, want, test.orig, have0)
|
2010-12-14 14:50:08 -07:00
|
|
|
}
|
|
|
|
// Check that the orig and extra slices were not modified.
|
|
|
|
if len(test.orig) != origLen {
|
|
|
|
t.Errorf("Append #%d origLen: have %v, want %v", i, len(test.orig), origLen)
|
|
|
|
}
|
|
|
|
if len(test.extra) != extraLen {
|
|
|
|
t.Errorf("Append #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
|
|
|
|
}
|
|
|
|
// Test AppendSlice.
|
2011-04-25 11:39:16 -06:00
|
|
|
a1 := ValueOf(test.orig)
|
2010-12-14 14:50:08 -07:00
|
|
|
have1 := AppendSlice(a1, e1).Interface().([]int)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
if !sameInts(have1, want) {
|
2010-12-14 14:50:08 -07:00
|
|
|
t.Errorf("AppendSlice #%d: have %v, want %v", i, have1, want)
|
|
|
|
}
|
|
|
|
// Check that the orig and extra slices were not modified.
|
|
|
|
if len(test.orig) != origLen {
|
|
|
|
t.Errorf("AppendSlice #%d origLen: have %v, want %v", i, len(test.orig), origLen)
|
|
|
|
}
|
|
|
|
if len(test.extra) != extraLen {
|
|
|
|
t.Errorf("AppendSlice #%d extraLen: have %v, want %v", i, len(test.extra), extraLen)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCopy(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
a := []int{1, 2, 3, 4, 10, 9, 8, 7}
|
|
|
|
b := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
|
|
|
|
c := []int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
|
2008-12-10 16:55:59 -07:00
|
|
|
for i := 0; i < len(b); i++ {
|
|
|
|
if b[i] != c[i] {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Fatalf("b != c before test")
|
2008-12-10 16:55:59 -07:00
|
|
|
}
|
|
|
|
}
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
a1 := a
|
|
|
|
b1 := b
|
2011-04-25 11:39:16 -06:00
|
|
|
aa := ValueOf(&a1).Elem()
|
|
|
|
ab := ValueOf(&b1).Elem()
|
2008-12-18 23:37:22 -07:00
|
|
|
for tocopy := 1; tocopy <= 7; tocopy++ {
|
2009-12-15 16:40:16 -07:00
|
|
|
aa.SetLen(tocopy)
|
2010-12-12 02:27:29 -07:00
|
|
|
Copy(ab, aa)
|
2009-12-15 16:40:16 -07:00
|
|
|
aa.SetLen(8)
|
2008-12-10 16:55:59 -07:00
|
|
|
for i := 0; i < tocopy; i++ {
|
|
|
|
if a[i] != b[i] {
|
2009-07-07 12:03:12 -06:00
|
|
|
t.Errorf("(i) tocopy=%d a[%d]=%d, b[%d]=%d",
|
2009-11-09 13:07:39 -07:00
|
|
|
tocopy, i, a[i], i, b[i])
|
2008-12-10 16:55:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := tocopy; i < len(b); i++ {
|
|
|
|
if b[i] != c[i] {
|
|
|
|
if i < len(a) {
|
2009-07-07 12:03:12 -06:00
|
|
|
t.Errorf("(ii) tocopy=%d a[%d]=%d, b[%d]=%d, c[%d]=%d",
|
2009-11-09 13:07:39 -07:00
|
|
|
tocopy, i, a[i], i, b[i], i, c[i])
|
2008-12-10 16:55:59 -07:00
|
|
|
} else {
|
2009-07-07 12:03:12 -06:00
|
|
|
t.Errorf("(iii) tocopy=%d b[%d]=%d, c[%d]=%d",
|
2009-11-09 13:07:39 -07:00
|
|
|
tocopy, i, b[i], i, c[i])
|
2008-12-10 16:55:59 -07:00
|
|
|
}
|
2008-12-18 23:37:22 -07:00
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Logf("tocopy=%d elem %d is okay\n", tocopy, i)
|
2008-12-10 16:55:59 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-01-09 01:17:46 -07:00
|
|
|
|
2011-04-27 15:22:53 -06:00
|
|
|
func TestCopyArray(t *testing.T) {
|
|
|
|
a := [8]int{1, 2, 3, 4, 10, 9, 8, 7}
|
|
|
|
b := [11]int{11, 22, 33, 44, 1010, 99, 88, 77, 66, 55, 44}
|
|
|
|
c := b
|
|
|
|
aa := ValueOf(&a).Elem()
|
|
|
|
ab := ValueOf(&b).Elem()
|
|
|
|
Copy(ab, aa)
|
|
|
|
for i := 0; i < len(a); i++ {
|
|
|
|
if a[i] != b[i] {
|
|
|
|
t.Errorf("(i) a[%d]=%d, b[%d]=%d", i, a[i], i, b[i])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for i := len(a); i < len(b); i++ {
|
|
|
|
if b[i] != c[i] {
|
2011-04-28 11:16:41 -06:00
|
|
|
t.Errorf("(ii) b[%d]=%d, c[%d]=%d", i, b[i], i, c[i])
|
2011-04-27 15:22:53 -06:00
|
|
|
} else {
|
|
|
|
t.Logf("elem %d is okay\n", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func TestBigUnnamedStruct(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
b := struct{ a, b, c, d int64 }{1, 2, 3, 4}
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(b)
|
2009-11-05 15:23:20 -07:00
|
|
|
b1 := v.Interface().(struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a, b, c, d int64
|
|
|
|
})
|
2009-01-09 01:17:46 -07:00
|
|
|
if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d {
|
2011-04-25 11:39:16 -06:00
|
|
|
t.Errorf("ValueOf(%v).Interface().(*Big) = %v", b, b1)
|
2009-01-09 01:17:46 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-01-16 13:48:07 -07:00
|
|
|
type big struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a, b, c, d, e int64
|
2009-01-09 01:17:46 -07:00
|
|
|
}
|
2009-11-05 15:23:20 -07:00
|
|
|
|
2009-01-20 15:40:40 -07:00
|
|
|
func TestBigStruct(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
b := big{1, 2, 3, 4, 5}
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(b)
|
2009-12-15 16:40:16 -07:00
|
|
|
b1 := v.Interface().(big)
|
2009-01-09 01:17:46 -07:00
|
|
|
if b1.a != b.a || b1.b != b.b || b1.c != b.c || b1.d != b.d || b1.e != b.e {
|
2011-04-25 11:39:16 -06:00
|
|
|
t.Errorf("ValueOf(%v).Interface().(big) = %v", b, b1)
|
2009-01-09 01:17:46 -07:00
|
|
|
}
|
|
|
|
}
|
2009-04-01 23:20:18 -06:00
|
|
|
|
|
|
|
type Basic struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x int
|
|
|
|
y float32
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
|
2009-04-15 01:55:58 -06:00
|
|
|
type NotBasic Basic
|
|
|
|
|
2009-04-01 23:20:18 -06:00
|
|
|
type DeepEqualTest struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a, b interface{}
|
|
|
|
eq bool
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
|
2012-02-23 22:25:39 -07:00
|
|
|
// Simple functions for DeepEqual tests.
|
|
|
|
var (
|
|
|
|
fn1 func() // nil.
|
|
|
|
fn2 func() // nil.
|
|
|
|
fn3 = func() { fn1() } // Not nil.
|
|
|
|
)
|
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var deepEqualTests = []DeepEqualTest{
|
2009-04-01 23:20:18 -06:00
|
|
|
// Equalities
|
2012-04-22 20:07:02 -06:00
|
|
|
{nil, nil, true},
|
2010-10-22 11:06:33 -06:00
|
|
|
{1, 1, true},
|
|
|
|
{int32(1), int32(1), true},
|
|
|
|
{0.5, 0.5, true},
|
|
|
|
{float32(0.5), float32(0.5), true},
|
|
|
|
{"hello", "hello", true},
|
|
|
|
{make([]int, 10), make([]int, 10), true},
|
|
|
|
{&[3]int{1, 2, 3}, &[3]int{1, 2, 3}, true},
|
|
|
|
{Basic{1, 0.5}, Basic{1, 0.5}, true},
|
2011-11-01 20:05:34 -06:00
|
|
|
{error(nil), error(nil), true},
|
2010-10-22 11:06:33 -06:00
|
|
|
{map[int]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, true},
|
2012-02-23 22:25:39 -07:00
|
|
|
{fn1, fn2, true},
|
2009-07-01 17:45:09 -06:00
|
|
|
|
2009-04-01 23:20:18 -06:00
|
|
|
// Inequalities
|
2010-10-22 11:06:33 -06:00
|
|
|
{1, 2, false},
|
|
|
|
{int32(1), int32(2), false},
|
|
|
|
{0.5, 0.6, false},
|
|
|
|
{float32(0.5), float32(0.6), false},
|
|
|
|
{"hello", "hey", false},
|
|
|
|
{make([]int, 10), make([]int, 11), false},
|
|
|
|
{&[3]int{1, 2, 3}, &[3]int{1, 2, 4}, false},
|
|
|
|
{Basic{1, 0.5}, Basic{1, 0.6}, false},
|
|
|
|
{Basic{1, 0}, Basic{2, 0}, false},
|
|
|
|
{map[int]string{1: "one", 3: "two"}, map[int]string{2: "two", 1: "one"}, false},
|
|
|
|
{map[int]string{1: "one", 2: "txo"}, map[int]string{2: "two", 1: "one"}, false},
|
|
|
|
{map[int]string{1: "one"}, map[int]string{2: "two", 1: "one"}, false},
|
|
|
|
{map[int]string{2: "two", 1: "one"}, map[int]string{1: "one"}, false},
|
|
|
|
{nil, 1, false},
|
|
|
|
{1, nil, false},
|
2012-02-23 22:25:39 -07:00
|
|
|
{fn1, fn3, false},
|
|
|
|
{fn3, fn3, false},
|
2009-07-01 17:45:09 -06:00
|
|
|
|
2011-11-14 14:11:15 -07:00
|
|
|
// Nil vs empty: not the same.
|
|
|
|
{[]int{}, []int(nil), false},
|
|
|
|
{[]int{}, []int{}, true},
|
|
|
|
{[]int(nil), []int(nil), true},
|
|
|
|
{map[int]int{}, map[int]int(nil), false},
|
|
|
|
{map[int]int{}, map[int]int{}, true},
|
|
|
|
{map[int]int(nil), map[int]int(nil), true},
|
|
|
|
|
2009-04-01 23:20:18 -06:00
|
|
|
// Mismatched types
|
2010-10-22 11:06:33 -06:00
|
|
|
{1, 1.0, false},
|
|
|
|
{int32(1), int64(1), false},
|
|
|
|
{0.5, "hello", false},
|
|
|
|
{[]int{1, 2, 3}, [3]int{1, 2, 3}, false},
|
|
|
|
{&[3]interface{}{1, 2, 4}, &[3]interface{}{1, 2, "s"}, false},
|
|
|
|
{Basic{1, 0.5}, NotBasic{1, 0.5}, false},
|
|
|
|
{map[uint]string{1: "one", 2: "two"}, map[int]string{2: "two", 1: "one"}, false},
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeepEqual(t *testing.T) {
|
2009-09-15 10:41:59 -06:00
|
|
|
for _, test := range deepEqualTests {
|
2009-04-01 23:20:18 -06:00
|
|
|
if r := DeepEqual(test.a, test.b); r != test.eq {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("DeepEqual(%v, %v) = %v, want %v", test.a, test.b, r, test.eq)
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
func TestTypeOf(t *testing.T) {
|
2012-04-22 20:07:02 -06:00
|
|
|
// Special case for nil
|
|
|
|
if typ := TypeOf(nil); typ != nil {
|
|
|
|
t.Errorf("expected nil type for nil value; got %v", typ)
|
|
|
|
}
|
2009-09-15 10:41:59 -06:00
|
|
|
for _, test := range deepEqualTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(test.a)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if !v.IsValid() {
|
2009-11-09 13:07:39 -07:00
|
|
|
continue
|
2009-07-07 12:03:12 -06:00
|
|
|
}
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf(test.a)
|
2009-06-25 15:25:38 -06:00
|
|
|
if typ != v.Type() {
|
2011-04-25 11:39:16 -06:00
|
|
|
t.Errorf("TypeOf(%v) = %v, but ValueOf(%v).Type() = %v", test.a, typ, test.a, v.Type())
|
2009-06-25 15:25:38 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-10 12:20:10 -06:00
|
|
|
type Recursive struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x int
|
|
|
|
r *Recursive
|
2009-07-10 12:20:10 -06:00
|
|
|
}
|
|
|
|
|
2009-04-01 23:20:18 -06:00
|
|
|
func TestDeepEqualRecursiveStruct(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
a, b := new(Recursive), new(Recursive)
|
|
|
|
*a = Recursive{12, a}
|
|
|
|
*b = Recursive{12, b}
|
2009-04-01 23:20:18 -06:00
|
|
|
if !DeepEqual(a, b) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("DeepEqual(recursive same) = false, want true")
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-06-20 13:16:25 -06:00
|
|
|
type _Complex struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int
|
2010-06-20 13:16:25 -06:00
|
|
|
b [3]*_Complex
|
2009-12-15 16:40:16 -07:00
|
|
|
c *string
|
2011-01-19 21:09:00 -07:00
|
|
|
d map[float64]float64
|
2009-07-10 12:20:10 -06:00
|
|
|
}
|
|
|
|
|
2009-04-01 23:20:18 -06:00
|
|
|
func TestDeepEqualComplexStruct(t *testing.T) {
|
2011-01-19 21:09:00 -07:00
|
|
|
m := make(map[float64]float64)
|
2009-12-15 16:40:16 -07:00
|
|
|
stra, strb := "hello", "hello"
|
2010-06-20 13:16:25 -06:00
|
|
|
a, b := new(_Complex), new(_Complex)
|
|
|
|
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
|
|
|
|
*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
|
2009-04-01 23:20:18 -06:00
|
|
|
if !DeepEqual(a, b) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("DeepEqual(complex same) = false, want true")
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeepEqualComplexStructInequality(t *testing.T) {
|
2011-01-19 21:09:00 -07:00
|
|
|
m := make(map[float64]float64)
|
2009-12-15 16:40:16 -07:00
|
|
|
stra, strb := "hello", "helloo" // Difference is here
|
2010-06-20 13:16:25 -06:00
|
|
|
a, b := new(_Complex), new(_Complex)
|
|
|
|
*a = _Complex{5, [3]*_Complex{a, b, a}, &stra, m}
|
|
|
|
*b = _Complex{5, [3]*_Complex{b, a, a}, &strb, m}
|
2009-04-01 23:20:18 -06:00
|
|
|
if DeepEqual(a, b) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("DeepEqual(complex different) = true, want false")
|
2009-04-01 23:20:18 -06:00
|
|
|
}
|
|
|
|
}
|
2009-04-29 23:16:53 -06:00
|
|
|
|
2011-05-03 08:38:37 -06:00
|
|
|
type UnexpT struct {
|
|
|
|
m map[int]int
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestDeepEqualUnexportedMap(t *testing.T) {
|
|
|
|
// Check that DeepEqual can look at unexported fields.
|
|
|
|
x1 := UnexpT{map[int]int{1: 2}}
|
|
|
|
x2 := UnexpT{map[int]int{1: 2}}
|
|
|
|
if !DeepEqual(&x1, &x2) {
|
|
|
|
t.Error("DeepEqual(x1, x2) = false, want true")
|
|
|
|
}
|
|
|
|
|
|
|
|
y1 := UnexpT{map[int]int{2: 3}}
|
|
|
|
if DeepEqual(&x1, &y1) {
|
|
|
|
t.Error("DeepEqual(x1, y1) = true, want false")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-29 23:16:53 -06:00
|
|
|
func check2ndField(x interface{}, offs uintptr, t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
s := ValueOf(x)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
f := s.Type().Field(1)
|
2009-07-07 12:03:12 -06:00
|
|
|
if f.Offset != offs {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("mismatched offsets in structure alignment:", f.Offset, offs)
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check that structure alignment & offsets viewed through reflect agree with those
|
|
|
|
// from the compiler itself.
|
|
|
|
func TestAlignment(t *testing.T) {
|
|
|
|
type T1inner struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a int
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
|
|
|
type T1 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
T1inner
|
|
|
|
f int
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
|
|
|
type T2inner struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a, b int
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
|
|
|
type T2 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
T2inner
|
|
|
|
f int
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
x := T1{T1inner{2}, 17}
|
|
|
|
check2ndField(x, uintptr(unsafe.Pointer(&x.f))-uintptr(unsafe.Pointer(&x)), t)
|
2009-04-29 23:16:53 -06:00
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
x1 := T2{T2inner{2, 3}, 17}
|
|
|
|
check2ndField(x1, uintptr(unsafe.Pointer(&x1.f))-uintptr(unsafe.Pointer(&x1)), t)
|
2009-04-29 23:16:53 -06:00
|
|
|
}
|
2009-05-12 15:57:44 -06:00
|
|
|
|
|
|
|
func Nil(a interface{}, t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
n := ValueOf(a).Field(0)
|
2009-05-12 15:57:44 -06:00
|
|
|
if !n.IsNil() {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%v should be nil", a)
|
2009-05-12 15:57:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func NotNil(a interface{}, t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
n := ValueOf(a).Field(0)
|
2009-05-12 15:57:44 -06:00
|
|
|
if n.IsNil() {
|
2011-04-25 11:39:16 -06:00
|
|
|
t.Errorf("value of type %v should not be nil", ValueOf(a).Type().String())
|
2009-05-12 15:57:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestIsNil(t *testing.T) {
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
// These implement IsNil.
|
2009-07-07 12:03:12 -06:00
|
|
|
// Wrap in extra struct to hide interface type.
|
|
|
|
doNil := []interface{}{
|
2009-11-06 17:33:53 -07:00
|
|
|
struct{ x *int }{},
|
|
|
|
struct{ x interface{} }{},
|
|
|
|
struct{ x map[string]int }{},
|
|
|
|
struct{ x func() bool }{},
|
|
|
|
struct{ x chan int }{},
|
|
|
|
struct{ x []string }{},
|
2009-12-15 16:40:16 -07:00
|
|
|
}
|
2009-09-15 10:41:59 -06:00
|
|
|
for _, ts := range doNil {
|
2011-04-25 11:39:16 -06:00
|
|
|
ty := TypeOf(ts).Field(0).Type
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v := Zero(ty)
|
|
|
|
v.IsNil() // panics if not okay to call
|
2009-05-12 15:57:44 -06:00
|
|
|
}
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2009-05-12 15:57:44 -06:00
|
|
|
// Check the implementations
|
2009-11-05 15:23:20 -07:00
|
|
|
var pi struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x *int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(pi, t)
|
|
|
|
pi.x = new(int)
|
|
|
|
NotNil(pi, t)
|
2009-05-12 15:57:44 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var si struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x []int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(si, t)
|
|
|
|
si.x = make([]int, 10)
|
|
|
|
NotNil(si, t)
|
2009-05-12 15:57:44 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var ci struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x chan int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(ci, t)
|
|
|
|
ci.x = make(chan int)
|
|
|
|
NotNil(ci, t)
|
2009-07-07 12:03:12 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var mi struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x map[int]int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(mi, t)
|
|
|
|
mi.x = make(map[int]int)
|
|
|
|
NotNil(mi, t)
|
2009-05-12 15:57:44 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var ii struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x interface{}
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(ii, t)
|
|
|
|
ii.x = 2
|
|
|
|
NotNil(ii, t)
|
2009-05-12 15:57:44 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var fi struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x func(t *testing.T)
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-12-15 16:40:16 -07:00
|
|
|
Nil(fi, t)
|
|
|
|
fi.x = TestIsNil
|
|
|
|
NotNil(fi, t)
|
2009-05-12 15:57:44 -06:00
|
|
|
}
|
2009-05-21 12:50:20 -06:00
|
|
|
|
|
|
|
func TestInterfaceExtraction(t *testing.T) {
|
|
|
|
var s struct {
|
2011-10-17 16:48:45 -06:00
|
|
|
W io.Writer
|
2009-05-21 12:50:20 -06:00
|
|
|
}
|
|
|
|
|
2011-10-17 16:48:45 -06:00
|
|
|
s.W = os.Stdout
|
2011-04-25 11:39:16 -06:00
|
|
|
v := Indirect(ValueOf(&s)).Field(0).Interface()
|
2011-10-17 16:48:45 -06:00
|
|
|
if v != s.W.(interface{}) {
|
|
|
|
t.Error("Interface() on interface: ", v, s.W)
|
2009-05-21 12:50:20 -06:00
|
|
|
}
|
|
|
|
}
|
2009-05-21 15:06:43 -06:00
|
|
|
|
2009-06-15 19:35:04 -06:00
|
|
|
func TestNilPtrValueSub(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
var pi *int
|
2011-04-25 11:39:16 -06:00
|
|
|
if pv := ValueOf(pi); pv.Elem().IsValid() {
|
|
|
|
t.Error("ValueOf((*int)(nil)).Elem().IsValid()")
|
2009-06-15 19:35:04 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-08 14:55:57 -06:00
|
|
|
|
2009-07-08 16:00:54 -06:00
|
|
|
func TestMap(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
m := map[string]int{"a": 1, "b": 2}
|
2011-04-25 11:39:16 -06:00
|
|
|
mv := ValueOf(m)
|
2009-07-08 14:55:57 -06:00
|
|
|
if n := mv.Len(); n != len(m) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Len = %d, want %d", n, len(m))
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
keys := mv.MapKeys()
|
|
|
|
newmap := MakeMap(mv.Type())
|
2009-07-08 14:55:57 -06:00
|
|
|
for k, v := range m {
|
|
|
|
// Check that returned Keys match keys in range.
|
2011-10-17 19:47:34 -06:00
|
|
|
// These aren't required to be in the same order.
|
|
|
|
seen := false
|
|
|
|
for _, kv := range keys {
|
|
|
|
if kv.String() == k {
|
|
|
|
seen = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !seen {
|
|
|
|
t.Errorf("Missing key %q", k)
|
|
|
|
}
|
2009-07-08 14:55:57 -06:00
|
|
|
|
|
|
|
// Check that value lookup is correct.
|
2011-04-25 11:39:16 -06:00
|
|
|
vv := mv.MapIndex(ValueOf(k))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if vi := vv.Int(); vi != int64(v) {
|
2010-12-07 14:42:54 -07:00
|
|
|
t.Errorf("Key %q: have value %d, want %d", k, vi, v)
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Copy into new map.
|
2011-04-25 11:39:16 -06:00
|
|
|
newmap.SetMapIndex(ValueOf(k), ValueOf(v))
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
2011-04-25 11:39:16 -06:00
|
|
|
vv := mv.MapIndex(ValueOf("not-present"))
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if vv.IsValid() {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Invalid key: got non-nil value %s", valueToString(vv))
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
|
|
|
|
2009-12-15 16:40:16 -07:00
|
|
|
newm := newmap.Interface().(map[string]int)
|
2009-07-08 14:55:57 -06:00
|
|
|
if len(newm) != len(m) {
|
2013-09-23 11:19:08 -06:00
|
|
|
t.Errorf("length after copy: newm=%d, m=%d", len(newm), len(m))
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
for k, v := range newm {
|
2009-12-15 16:40:16 -07:00
|
|
|
mv, ok := m[k]
|
2009-07-08 14:55:57 -06:00
|
|
|
if mv != v {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("newm[%q] = %d, but m[%q] = %d, %v", k, v, k, mv, ok)
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-08 16:00:54 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
newmap.SetMapIndex(ValueOf("a"), Value{})
|
2009-12-15 16:40:16 -07:00
|
|
|
v, ok := newm["a"]
|
2009-07-08 14:55:57 -06:00
|
|
|
if ok {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("newm[\"a\"] = %d after delete", v)
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
2010-04-20 18:02:08 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
mv = ValueOf(&m).Elem()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
mv.Set(Zero(mv.Type()))
|
2010-04-20 18:02:08 -06:00
|
|
|
if m != nil {
|
|
|
|
t.Errorf("mv.Set(nil) failed")
|
|
|
|
}
|
2009-07-08 14:55:57 -06:00
|
|
|
}
|
2009-07-08 16:00:54 -06:00
|
|
|
|
|
|
|
func TestChan(t *testing.T) {
|
|
|
|
for loop := 0; loop < 2; loop++ {
|
2009-12-15 16:40:16 -07:00
|
|
|
var c chan int
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
var cv Value
|
2009-07-08 16:00:54 -06:00
|
|
|
|
|
|
|
// check both ways to allocate channels
|
|
|
|
switch loop {
|
|
|
|
case 1:
|
2009-12-15 16:40:16 -07:00
|
|
|
c = make(chan int, 1)
|
2011-04-25 11:39:16 -06:00
|
|
|
cv = ValueOf(c)
|
2009-07-08 16:00:54 -06:00
|
|
|
case 0:
|
2011-04-25 11:39:16 -06:00
|
|
|
cv = MakeChan(TypeOf(c), 1)
|
2009-12-15 16:40:16 -07:00
|
|
|
c = cv.Interface().(chan int)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Send
|
2011-04-25 11:39:16 -06:00
|
|
|
cv.Send(ValueOf(2))
|
2009-07-08 16:00:54 -06:00
|
|
|
if i := <-c; i != 2 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("reflect Send 2, native recv %d", i)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Recv
|
2009-12-15 16:40:16 -07:00
|
|
|
c <- 3
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if i, ok := cv.Recv(); i.Int() != 3 || !ok {
|
|
|
|
t.Errorf("native send 3, reflect Recv %d, %t", i.Int(), ok)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TryRecv fail
|
2011-03-11 12:47:44 -07:00
|
|
|
val, ok := cv.TryRecv()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if val.IsValid() || ok {
|
2011-03-11 12:47:44 -07:00
|
|
|
t.Errorf("TryRecv on empty chan: %s, %t", valueToString(val), ok)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TryRecv success
|
2009-12-15 16:40:16 -07:00
|
|
|
c <- 4
|
2011-03-11 12:47:44 -07:00
|
|
|
val, ok = cv.TryRecv()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if !val.IsValid() {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("TryRecv on ready chan got nil")
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
} else if i := val.Int(); i != 4 || !ok {
|
2011-03-11 12:47:44 -07:00
|
|
|
t.Errorf("native send 4, TryRecv %d, %t", i, ok)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TrySend fail
|
2009-12-15 16:40:16 -07:00
|
|
|
c <- 100
|
2011-04-25 11:39:16 -06:00
|
|
|
ok = cv.TrySend(ValueOf(5))
|
2009-12-15 16:40:16 -07:00
|
|
|
i := <-c
|
2009-07-08 16:00:54 -06:00
|
|
|
if ok {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("TrySend on full chan succeeded: value %d", i)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// TrySend success
|
2011-04-25 11:39:16 -06:00
|
|
|
ok = cv.TrySend(ValueOf(6))
|
2009-07-08 16:00:54 -06:00
|
|
|
if !ok {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("TrySend on empty chan failed")
|
2009-07-08 16:00:54 -06:00
|
|
|
} else {
|
|
|
|
if i = <-c; i != 6 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("TrySend 6, recv %d", i)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
}
|
2009-08-26 11:47:18 -06:00
|
|
|
|
|
|
|
// Close
|
2009-12-15 16:40:16 -07:00
|
|
|
c <- 123
|
|
|
|
cv.Close()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if i, ok := cv.Recv(); i.Int() != 123 || !ok {
|
|
|
|
t.Errorf("send 123 then close; Recv %d, %t", i.Int(), ok)
|
2009-08-26 11:47:18 -06:00
|
|
|
}
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if i, ok := cv.Recv(); i.Int() != 0 || ok {
|
|
|
|
t.Errorf("after close Recv %d, %t", i.Int(), ok)
|
2009-08-26 11:47:18 -06:00
|
|
|
}
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// check creation of unbuffered channel
|
2009-12-15 16:40:16 -07:00
|
|
|
var c chan int
|
2011-04-25 11:39:16 -06:00
|
|
|
cv := MakeChan(TypeOf(c), 0)
|
2009-12-15 16:40:16 -07:00
|
|
|
c = cv.Interface().(chan int)
|
2011-04-25 11:39:16 -06:00
|
|
|
if cv.TrySend(ValueOf(7)) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("TrySend on sync chan succeeded")
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if v, ok := cv.TryRecv(); v.IsValid() || ok {
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
t.Errorf("TryRecv on sync chan succeeded: isvalid=%v ok=%v", v.IsValid(), ok)
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
2009-08-26 13:42:22 -06:00
|
|
|
|
|
|
|
// len/cap
|
2011-04-25 11:39:16 -06:00
|
|
|
cv = MakeChan(TypeOf(c), 10)
|
2009-12-15 16:40:16 -07:00
|
|
|
c = cv.Interface().(chan int)
|
2009-08-26 13:42:22 -06:00
|
|
|
for i := 0; i < 3; i++ {
|
2009-11-09 13:07:39 -07:00
|
|
|
c <- i
|
2009-08-26 13:42:22 -06:00
|
|
|
}
|
|
|
|
if l, m := cv.Len(), cv.Cap(); l != len(c) || m != cap(c) {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Len/Cap = %d/%d want %d/%d", l, m, len(c), cap(c))
|
2009-08-26 13:42:22 -06:00
|
|
|
}
|
2009-07-08 16:00:54 -06:00
|
|
|
}
|
|
|
|
|
2012-09-18 12:22:41 -06:00
|
|
|
// caseInfo describes a single case in a select test.
|
|
|
|
type caseInfo struct {
|
|
|
|
desc string
|
|
|
|
canSelect bool
|
|
|
|
recv Value
|
|
|
|
closed bool
|
|
|
|
helper func()
|
|
|
|
panic bool
|
|
|
|
}
|
|
|
|
|
2012-09-22 06:52:27 -06:00
|
|
|
var allselect = flag.Bool("allselect", false, "exhaustive select test")
|
|
|
|
|
2012-09-18 12:22:41 -06:00
|
|
|
func TestSelect(t *testing.T) {
|
|
|
|
selectWatch.once.Do(func() { go selectWatcher() })
|
|
|
|
|
|
|
|
var x exhaustive
|
|
|
|
nch := 0
|
|
|
|
newop := func(n int, cap int) (ch, val Value) {
|
|
|
|
nch++
|
|
|
|
if nch%101%2 == 1 {
|
|
|
|
c := make(chan int, cap)
|
|
|
|
ch = ValueOf(c)
|
|
|
|
val = ValueOf(n)
|
|
|
|
} else {
|
|
|
|
c := make(chan string, cap)
|
|
|
|
ch = ValueOf(c)
|
|
|
|
val = ValueOf(fmt.Sprint(n))
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
for n := 0; x.Next(); n++ {
|
|
|
|
if testing.Short() && n >= 1000 {
|
|
|
|
break
|
|
|
|
}
|
2012-09-22 06:52:27 -06:00
|
|
|
if n >= 100000 && !*allselect {
|
|
|
|
break
|
|
|
|
}
|
2012-09-18 12:22:41 -06:00
|
|
|
if n%100000 == 0 && testing.Verbose() {
|
|
|
|
println("TestSelect", n)
|
|
|
|
}
|
|
|
|
var cases []SelectCase
|
|
|
|
var info []caseInfo
|
|
|
|
|
|
|
|
// Ready send.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch, val := newop(len(cases), 1)
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectSend,
|
|
|
|
Chan: ch,
|
|
|
|
Send: val,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "ready send", canSelect: true})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Ready recv.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch, val := newop(len(cases), 1)
|
|
|
|
ch.Send(val)
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectRecv,
|
|
|
|
Chan: ch,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "ready recv", canSelect: true, recv: val})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Blocking send.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch, val := newop(len(cases), 0)
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectSend,
|
|
|
|
Chan: ch,
|
|
|
|
Send: val,
|
|
|
|
})
|
|
|
|
// Let it execute?
|
|
|
|
if x.Maybe() {
|
|
|
|
f := func() { ch.Recv() }
|
|
|
|
info = append(info, caseInfo{desc: "blocking send", helper: f})
|
|
|
|
} else {
|
|
|
|
info = append(info, caseInfo{desc: "blocking send"})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Blocking recv.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch, val := newop(len(cases), 0)
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectRecv,
|
|
|
|
Chan: ch,
|
|
|
|
})
|
|
|
|
// Let it execute?
|
|
|
|
if x.Maybe() {
|
|
|
|
f := func() { ch.Send(val) }
|
|
|
|
info = append(info, caseInfo{desc: "blocking recv", recv: val, helper: f})
|
|
|
|
} else {
|
|
|
|
info = append(info, caseInfo{desc: "blocking recv"})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zero Chan send.
|
|
|
|
if x.Maybe() {
|
|
|
|
// Maybe include value to send.
|
|
|
|
var val Value
|
|
|
|
if x.Maybe() {
|
|
|
|
val = ValueOf(100)
|
|
|
|
}
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectSend,
|
|
|
|
Send: val,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "zero Chan send"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// Zero Chan receive.
|
|
|
|
if x.Maybe() {
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectRecv,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "zero Chan recv"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// nil Chan send.
|
|
|
|
if x.Maybe() {
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectSend,
|
|
|
|
Chan: ValueOf((chan int)(nil)),
|
|
|
|
Send: ValueOf(101),
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "nil Chan send"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// nil Chan recv.
|
|
|
|
if x.Maybe() {
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectRecv,
|
|
|
|
Chan: ValueOf((chan int)(nil)),
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "nil Chan recv"})
|
|
|
|
}
|
|
|
|
|
|
|
|
// closed Chan send.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch := make(chan int)
|
|
|
|
close(ch)
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectSend,
|
|
|
|
Chan: ValueOf(ch),
|
|
|
|
Send: ValueOf(101),
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "closed Chan send", canSelect: true, panic: true})
|
|
|
|
}
|
|
|
|
|
|
|
|
// closed Chan recv.
|
|
|
|
if x.Maybe() {
|
|
|
|
ch, val := newop(len(cases), 0)
|
|
|
|
ch.Close()
|
|
|
|
val = Zero(val.Type())
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectRecv,
|
|
|
|
Chan: ch,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "closed Chan recv", canSelect: true, closed: true, recv: val})
|
|
|
|
}
|
|
|
|
|
|
|
|
var helper func() // goroutine to help the select complete
|
|
|
|
|
|
|
|
// Add default? Must be last case here, but will permute.
|
|
|
|
// Add the default if the select would otherwise
|
|
|
|
// block forever, and maybe add it anyway.
|
|
|
|
numCanSelect := 0
|
|
|
|
canProceed := false
|
|
|
|
canBlock := true
|
|
|
|
canPanic := false
|
|
|
|
helpers := []int{}
|
|
|
|
for i, c := range info {
|
|
|
|
if c.canSelect {
|
|
|
|
canProceed = true
|
|
|
|
canBlock = false
|
|
|
|
numCanSelect++
|
|
|
|
if c.panic {
|
|
|
|
canPanic = true
|
|
|
|
}
|
|
|
|
} else if c.helper != nil {
|
|
|
|
canProceed = true
|
|
|
|
helpers = append(helpers, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !canProceed || x.Maybe() {
|
|
|
|
cases = append(cases, SelectCase{
|
|
|
|
Dir: SelectDefault,
|
|
|
|
})
|
|
|
|
info = append(info, caseInfo{desc: "default", canSelect: canBlock})
|
|
|
|
numCanSelect++
|
|
|
|
} else if canBlock {
|
|
|
|
// Select needs to communicate with another goroutine.
|
|
|
|
cas := &info[helpers[x.Choose(len(helpers))]]
|
|
|
|
helper = cas.helper
|
|
|
|
cas.canSelect = true
|
|
|
|
numCanSelect++
|
|
|
|
}
|
|
|
|
|
|
|
|
// Permute cases and case info.
|
|
|
|
// Doing too much here makes the exhaustive loop
|
|
|
|
// too exhausting, so just do two swaps.
|
|
|
|
for loop := 0; loop < 2; loop++ {
|
|
|
|
i := x.Choose(len(cases))
|
|
|
|
j := x.Choose(len(cases))
|
|
|
|
cases[i], cases[j] = cases[j], cases[i]
|
|
|
|
info[i], info[j] = info[j], info[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
if helper != nil {
|
|
|
|
// We wait before kicking off a goroutine to satisfy a blocked select.
|
|
|
|
// The pause needs to be big enough to let the select block before
|
|
|
|
// we run the helper, but if we lose that race once in a while it's okay: the
|
|
|
|
// select will just proceed immediately. Not a big deal.
|
|
|
|
// For short tests we can grow [sic] the timeout a bit without fear of taking too long
|
|
|
|
pause := 10 * time.Microsecond
|
|
|
|
if testing.Short() {
|
|
|
|
pause = 100 * time.Microsecond
|
|
|
|
}
|
|
|
|
time.AfterFunc(pause, helper)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Run select.
|
|
|
|
i, recv, recvOK, panicErr := runSelect(cases, info)
|
|
|
|
if panicErr != nil && !canPanic {
|
|
|
|
t.Fatalf("%s\npanicked unexpectedly: %v", fmtSelect(info), panicErr)
|
|
|
|
}
|
|
|
|
if panicErr == nil && canPanic && numCanSelect == 1 {
|
|
|
|
t.Fatalf("%s\nselected #%d incorrectly (should panic)", fmtSelect(info), i)
|
|
|
|
}
|
|
|
|
if panicErr != nil {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
cas := info[i]
|
|
|
|
if !cas.canSelect {
|
|
|
|
recvStr := ""
|
|
|
|
if recv.IsValid() {
|
|
|
|
recvStr = fmt.Sprintf(", received %v, %v", recv.Interface(), recvOK)
|
|
|
|
}
|
|
|
|
t.Fatalf("%s\nselected #%d incorrectly%s", fmtSelect(info), i, recvStr)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if cas.panic {
|
|
|
|
t.Fatalf("%s\nselected #%d incorrectly (case should panic)", fmtSelect(info), i)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if cases[i].Dir == SelectRecv {
|
|
|
|
if !recv.IsValid() {
|
|
|
|
t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, cas.recv.Interface(), !cas.closed)
|
|
|
|
}
|
|
|
|
if !cas.recv.IsValid() {
|
|
|
|
t.Fatalf("%s\nselected #%d but internal error: missing recv value", fmtSelect(info), i)
|
|
|
|
}
|
|
|
|
if recv.Interface() != cas.recv.Interface() || recvOK != !cas.closed {
|
|
|
|
if recv.Interface() == cas.recv.Interface() && recvOK == !cas.closed {
|
|
|
|
t.Fatalf("%s\nselected #%d, got %#v, %v, and DeepEqual is broken on %T", fmtSelect(info), i, recv.Interface(), recvOK, recv.Interface())
|
|
|
|
}
|
|
|
|
t.Fatalf("%s\nselected #%d but got %#v, %v, want %#v, %v", fmtSelect(info), i, recv.Interface(), recvOK, cas.recv.Interface(), !cas.closed)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if recv.IsValid() || recvOK {
|
|
|
|
t.Fatalf("%s\nselected #%d but got %v, %v, want %v, %v", fmtSelect(info), i, recv, recvOK, Value{}, false)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// selectWatch and the selectWatcher are a watchdog mechanism for running Select.
|
|
|
|
// If the selectWatcher notices that the select has been blocked for >1 second, it prints
|
2012-10-30 14:38:01 -06:00
|
|
|
// an error describing the select and panics the entire test binary.
|
2012-09-18 12:22:41 -06:00
|
|
|
var selectWatch struct {
|
|
|
|
sync.Mutex
|
|
|
|
once sync.Once
|
|
|
|
now time.Time
|
|
|
|
info []caseInfo
|
|
|
|
}
|
|
|
|
|
|
|
|
func selectWatcher() {
|
|
|
|
for {
|
|
|
|
time.Sleep(1 * time.Second)
|
|
|
|
selectWatch.Lock()
|
|
|
|
if selectWatch.info != nil && time.Since(selectWatch.now) > 1*time.Second {
|
|
|
|
fmt.Fprintf(os.Stderr, "TestSelect:\n%s blocked indefinitely\n", fmtSelect(selectWatch.info))
|
|
|
|
panic("select stuck")
|
|
|
|
}
|
|
|
|
selectWatch.Unlock()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// runSelect runs a single select test.
|
|
|
|
// It returns the values returned by Select but also returns
|
|
|
|
// a panic value if the Select panics.
|
|
|
|
func runSelect(cases []SelectCase, info []caseInfo) (chosen int, recv Value, recvOK bool, panicErr interface{}) {
|
|
|
|
defer func() {
|
|
|
|
panicErr = recover()
|
|
|
|
|
|
|
|
selectWatch.Lock()
|
|
|
|
selectWatch.info = nil
|
|
|
|
selectWatch.Unlock()
|
|
|
|
}()
|
|
|
|
|
|
|
|
selectWatch.Lock()
|
|
|
|
selectWatch.now = time.Now()
|
|
|
|
selectWatch.info = info
|
|
|
|
selectWatch.Unlock()
|
|
|
|
|
|
|
|
chosen, recv, recvOK = Select(cases)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// fmtSelect formats the information about a single select test.
|
|
|
|
func fmtSelect(info []caseInfo) string {
|
|
|
|
var buf bytes.Buffer
|
|
|
|
fmt.Fprintf(&buf, "\nselect {\n")
|
|
|
|
for i, cas := range info {
|
|
|
|
fmt.Fprintf(&buf, "%d: %s", i, cas.desc)
|
|
|
|
if cas.recv.IsValid() {
|
|
|
|
fmt.Fprintf(&buf, " val=%#v", cas.recv.Interface())
|
|
|
|
}
|
|
|
|
if cas.canSelect {
|
|
|
|
fmt.Fprintf(&buf, " canselect")
|
|
|
|
}
|
|
|
|
if cas.panic {
|
|
|
|
fmt.Fprintf(&buf, " panic")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(&buf, "\n")
|
|
|
|
}
|
|
|
|
fmt.Fprintf(&buf, "}")
|
|
|
|
return buf.String()
|
|
|
|
}
|
|
|
|
|
2012-09-24 18:06:32 -06:00
|
|
|
type two [2]uintptr
|
|
|
|
|
2009-07-08 19:16:09 -06:00
|
|
|
// Difficult test for function call because of
|
|
|
|
// implicit padding between arguments.
|
2012-09-24 18:06:32 -06:00
|
|
|
func dummy(b byte, c int, d byte, e two, f byte, g float32, h byte) (i byte, j int, k byte, l two, m byte, n float32, o byte) {
|
|
|
|
return b, c, d, e, f, g, h
|
2009-07-08 19:16:09 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestFunc(t *testing.T) {
|
2012-09-24 18:06:32 -06:00
|
|
|
ret := ValueOf(dummy).Call([]Value{
|
|
|
|
ValueOf(byte(10)),
|
|
|
|
ValueOf(20),
|
|
|
|
ValueOf(byte(30)),
|
|
|
|
ValueOf(two{40, 50}),
|
|
|
|
ValueOf(byte(60)),
|
|
|
|
ValueOf(float32(70)),
|
|
|
|
ValueOf(byte(80)),
|
|
|
|
})
|
|
|
|
if len(ret) != 7 {
|
|
|
|
t.Fatalf("Call returned %d values, want 7", len(ret))
|
2009-07-08 19:16:09 -06:00
|
|
|
}
|
|
|
|
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
i := byte(ret[0].Uint())
|
|
|
|
j := int(ret[1].Int())
|
|
|
|
k := byte(ret[2].Uint())
|
2012-09-24 18:06:32 -06:00
|
|
|
l := ret[3].Interface().(two)
|
|
|
|
m := byte(ret[4].Uint())
|
|
|
|
n := float32(ret[5].Float())
|
|
|
|
o := byte(ret[6].Uint())
|
|
|
|
|
|
|
|
if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
|
|
|
|
t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMakeFunc(t *testing.T) {
|
|
|
|
f := dummy
|
|
|
|
fv := MakeFunc(TypeOf(f), func(in []Value) []Value { return in })
|
|
|
|
ValueOf(&f).Elem().Set(fv)
|
|
|
|
|
|
|
|
// Call g with small arguments so that there is
|
|
|
|
// something predictable (and different from the
|
|
|
|
// correct results) in those positions on the stack.
|
|
|
|
g := dummy
|
|
|
|
g(1, 2, 3, two{4, 5}, 6, 7, 8)
|
|
|
|
|
|
|
|
// Call constructed function f.
|
|
|
|
i, j, k, l, m, n, o := f(10, 20, 30, two{40, 50}, 60, 70, 80)
|
|
|
|
if i != 10 || j != 20 || k != 30 || l != (two{40, 50}) || m != 60 || n != 70 || o != 80 {
|
|
|
|
t.Errorf("Call returned %d, %d, %d, %v, %d, %g, %d; want 10, 20, 30, [40, 50], 60, 70, 80", i, j, k, l, m, n, o)
|
2009-07-08 19:16:09 -06:00
|
|
|
}
|
|
|
|
}
|
2009-07-09 18:27:49 -06:00
|
|
|
|
|
|
|
type Point struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
x, y int
|
2009-07-09 18:27:49 -06:00
|
|
|
}
|
|
|
|
|
2011-06-28 21:11:49 -06:00
|
|
|
// This will be index 0.
|
|
|
|
func (p Point) AnotherMethod(scale int) int {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
// This will be index 1.
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
func (p Point) Dist(scale int) int {
|
2013-03-21 14:59:16 -06:00
|
|
|
//println("Point.Dist", p.x, p.y, scale)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
return p.x*p.x*scale + p.y*p.y*scale
|
|
|
|
}
|
2009-07-09 18:27:49 -06:00
|
|
|
|
|
|
|
func TestMethod(t *testing.T) {
|
|
|
|
// Non-curried method of type.
|
2009-12-15 16:40:16 -07:00
|
|
|
p := Point{3, 4}
|
2011-06-28 21:11:49 -06:00
|
|
|
i := TypeOf(p).Method(1).Func.Call([]Value{ValueOf(p), ValueOf(10)})[0].Int()
|
2009-07-09 18:27:49 -06:00
|
|
|
if i != 250 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Type Method returned %d; want 250", i)
|
2009-07-09 18:27:49 -06:00
|
|
|
}
|
|
|
|
|
2011-06-28 21:11:49 -06:00
|
|
|
m, ok := TypeOf(p).MethodByName("Dist")
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("method by name failed")
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = m.Func.Call([]Value{ValueOf(p), ValueOf(11)})[0].Int()
|
|
|
|
if i != 275 {
|
|
|
|
t.Errorf("Type MethodByName returned %d; want 275", i)
|
2011-06-28 21:11:49 -06:00
|
|
|
}
|
|
|
|
|
2013-03-21 14:59:16 -06:00
|
|
|
i = TypeOf(&p).Method(1).Func.Call([]Value{ValueOf(&p), ValueOf(12)})[0].Int()
|
|
|
|
if i != 300 {
|
|
|
|
t.Errorf("Pointer Type Method returned %d; want 300", i)
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
2011-06-28 21:11:49 -06:00
|
|
|
m, ok = TypeOf(&p).MethodByName("Dist")
|
|
|
|
if !ok {
|
|
|
|
t.Fatalf("ptr method by name failed")
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = m.Func.Call([]Value{ValueOf(&p), ValueOf(13)})[0].Int()
|
|
|
|
if i != 325 {
|
|
|
|
t.Errorf("Pointer Type MethodByName returned %d; want 325", i)
|
2011-06-28 21:11:49 -06:00
|
|
|
}
|
|
|
|
|
2009-07-09 18:27:49 -06:00
|
|
|
// Curried method of value.
|
2012-10-04 22:03:50 -06:00
|
|
|
tfunc := TypeOf((func(int) int)(nil))
|
2011-11-16 17:18:25 -07:00
|
|
|
v := ValueOf(p).Method(1)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = v.Call([]Value{ValueOf(14)})[0].Int()
|
|
|
|
if i != 350 {
|
|
|
|
t.Errorf("Value Method returned %d; want 350", i)
|
|
|
|
}
|
|
|
|
v = ValueOf(p).MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = v.Call([]Value{ValueOf(15)})[0].Int()
|
|
|
|
if i != 375 {
|
|
|
|
t.Errorf("Value MethodByName returned %d; want 375", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Curried method of pointer.
|
|
|
|
v = ValueOf(&p).Method(1)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = v.Call([]Value{ValueOf(16)})[0].Int()
|
|
|
|
if i != 400 {
|
|
|
|
t.Errorf("Pointer Value Method returned %d; want 400", i)
|
|
|
|
}
|
|
|
|
v = ValueOf(&p).MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = v.Call([]Value{ValueOf(17)})[0].Int()
|
|
|
|
if i != 425 {
|
|
|
|
t.Errorf("Pointer Value MethodByName returned %d; want 425", i)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Curried method of interface value.
|
|
|
|
// Have to wrap interface value in a struct to get at it.
|
|
|
|
// Passing it to ValueOf directly would
|
|
|
|
// access the underlying Point, not the interface.
|
|
|
|
var x interface {
|
|
|
|
Dist(int) int
|
|
|
|
} = p
|
|
|
|
pv := ValueOf(&x).Elem()
|
|
|
|
v = pv.Method(0)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = v.Call([]Value{ValueOf(18)})[0].Int()
|
|
|
|
if i != 450 {
|
|
|
|
t.Errorf("Interface Method returned %d; want 450", i)
|
|
|
|
}
|
|
|
|
v = pv.MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = v.Call([]Value{ValueOf(19)})[0].Int()
|
|
|
|
if i != 475 {
|
|
|
|
t.Errorf("Interface MethodByName returned %d; want 475", i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMethodValue(t *testing.T) {
|
|
|
|
p := Point{3, 4}
|
|
|
|
var i int64
|
|
|
|
|
|
|
|
// Curried method of value.
|
|
|
|
tfunc := TypeOf((func(int) int)(nil))
|
|
|
|
v := ValueOf(p).Method(1)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Value Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(10)})[0].Int()
|
2009-07-09 18:27:49 -06:00
|
|
|
if i != 250 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Value Method returned %d; want 250", i)
|
2009-07-09 18:27:49 -06:00
|
|
|
}
|
2011-11-16 17:18:25 -07:00
|
|
|
v = ValueOf(p).MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Value MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(11)})[0].Int()
|
|
|
|
if i != 275 {
|
|
|
|
t.Errorf("Value MethodByName returned %d; want 275", i)
|
2011-06-28 21:11:49 -06:00
|
|
|
}
|
2009-07-09 18:27:49 -06:00
|
|
|
|
2011-03-03 11:20:17 -07:00
|
|
|
// Curried method of pointer.
|
2011-11-16 17:18:25 -07:00
|
|
|
v = ValueOf(&p).Method(1)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Value Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(12)})[0].Int()
|
|
|
|
if i != 300 {
|
|
|
|
t.Errorf("Pointer Value Method returned %d; want 300", i)
|
2011-06-28 21:11:49 -06:00
|
|
|
}
|
2011-11-16 17:18:25 -07:00
|
|
|
v = ValueOf(&p).MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-03-21 14:59:16 -06:00
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(13)})[0].Int()
|
|
|
|
if i != 325 {
|
|
|
|
t.Errorf("Pointer Value MethodByName returned %d; want 325", i)
|
2011-03-03 11:20:17 -07:00
|
|
|
}
|
|
|
|
|
2013-09-17 16:22:42 -06:00
|
|
|
// Curried method of pointer to pointer.
|
|
|
|
pp := &p
|
|
|
|
v = ValueOf(&pp).Elem().Method(1)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Pointer Value Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(14)})[0].Int()
|
|
|
|
if i != 350 {
|
|
|
|
t.Errorf("Pointer Pointer Value Method returned %d; want 350", i)
|
|
|
|
}
|
|
|
|
v = ValueOf(&pp).Elem().MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Pointer Pointer Value MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(15)})[0].Int()
|
|
|
|
if i != 375 {
|
|
|
|
t.Errorf("Pointer Pointer Value MethodByName returned %d; want 375", i)
|
|
|
|
}
|
|
|
|
|
2009-07-09 18:27:49 -06:00
|
|
|
// Curried method of interface value.
|
|
|
|
// Have to wrap interface value in a struct to get at it.
|
2011-04-25 11:39:16 -06:00
|
|
|
// Passing it to ValueOf directly would
|
2009-07-09 18:27:49 -06:00
|
|
|
// access the underlying Point, not the interface.
|
2009-11-05 15:23:20 -07:00
|
|
|
var s = struct {
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
X interface {
|
2009-12-15 16:40:16 -07:00
|
|
|
Dist(int) int
|
|
|
|
}
|
|
|
|
}{p}
|
2011-04-25 11:39:16 -06:00
|
|
|
pv := ValueOf(s).Field(0)
|
2011-11-16 17:18:25 -07:00
|
|
|
v = pv.Method(0)
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Interface Method Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-09-17 16:22:42 -06:00
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(16)})[0].Int()
|
|
|
|
if i != 400 {
|
|
|
|
t.Errorf("Interface Method returned %d; want 400", i)
|
2009-07-09 18:27:49 -06:00
|
|
|
}
|
2011-11-16 17:18:25 -07:00
|
|
|
v = pv.MethodByName("Dist")
|
|
|
|
if tt := v.Type(); tt != tfunc {
|
|
|
|
t.Errorf("Interface MethodByName Type is %s; want %s", tt, tfunc)
|
|
|
|
}
|
2013-09-17 16:22:42 -06:00
|
|
|
i = ValueOf(v.Interface()).Call([]Value{ValueOf(17)})[0].Int()
|
|
|
|
if i != 425 {
|
|
|
|
t.Errorf("Interface MethodByName returned %d; want 425", i)
|
2011-06-28 21:11:49 -06:00
|
|
|
}
|
2009-07-09 18:27:49 -06:00
|
|
|
}
|
2009-07-10 17:32:26 -06:00
|
|
|
|
2013-03-21 14:59:16 -06:00
|
|
|
// Reflect version of $GOROOT/test/method5.go
|
|
|
|
|
|
|
|
// Concrete types implementing M method.
|
|
|
|
// Smaller than a word, word-sized, larger than a word.
|
|
|
|
// Value and pointer receivers.
|
|
|
|
|
|
|
|
type Tinter interface {
|
|
|
|
M(int, byte) (byte, int)
|
|
|
|
}
|
|
|
|
|
|
|
|
type Tsmallv byte
|
|
|
|
|
|
|
|
func (v Tsmallv) M(x int, b byte) (byte, int) { return b, x + int(v) }
|
|
|
|
|
|
|
|
type Tsmallp byte
|
|
|
|
|
|
|
|
func (p *Tsmallp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
|
|
|
|
|
|
|
|
type Twordv uintptr
|
|
|
|
|
|
|
|
func (v Twordv) M(x int, b byte) (byte, int) { return b, x + int(v) }
|
|
|
|
|
|
|
|
type Twordp uintptr
|
|
|
|
|
|
|
|
func (p *Twordp) M(x int, b byte) (byte, int) { return b, x + int(*p) }
|
|
|
|
|
|
|
|
type Tbigv [2]uintptr
|
|
|
|
|
|
|
|
func (v Tbigv) M(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
|
|
|
|
|
|
|
|
type Tbigp [2]uintptr
|
|
|
|
|
|
|
|
func (p *Tbigp) M(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
|
|
|
|
|
|
|
|
// Again, with an unexported method.
|
|
|
|
|
|
|
|
type tsmallv byte
|
|
|
|
|
|
|
|
func (v tsmallv) m(x int, b byte) (byte, int) { return b, x + int(v) }
|
|
|
|
|
|
|
|
type tsmallp byte
|
|
|
|
|
|
|
|
func (p *tsmallp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
|
|
|
|
|
|
|
|
type twordv uintptr
|
|
|
|
|
|
|
|
func (v twordv) m(x int, b byte) (byte, int) { return b, x + int(v) }
|
|
|
|
|
|
|
|
type twordp uintptr
|
|
|
|
|
|
|
|
func (p *twordp) m(x int, b byte) (byte, int) { return b, x + int(*p) }
|
|
|
|
|
|
|
|
type tbigv [2]uintptr
|
|
|
|
|
|
|
|
func (v tbigv) m(x int, b byte) (byte, int) { return b, x + int(v[0]) + int(v[1]) }
|
|
|
|
|
|
|
|
type tbigp [2]uintptr
|
|
|
|
|
|
|
|
func (p *tbigp) m(x int, b byte) (byte, int) { return b, x + int(p[0]) + int(p[1]) }
|
|
|
|
|
|
|
|
type tinter interface {
|
|
|
|
m(int, byte) (byte, int)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Embedding via pointer.
|
|
|
|
|
|
|
|
type Tm1 struct {
|
|
|
|
Tm2
|
|
|
|
}
|
|
|
|
|
|
|
|
type Tm2 struct {
|
|
|
|
*Tm3
|
|
|
|
}
|
|
|
|
|
|
|
|
type Tm3 struct {
|
|
|
|
*Tm4
|
|
|
|
}
|
|
|
|
|
|
|
|
type Tm4 struct {
|
|
|
|
}
|
|
|
|
|
|
|
|
func (t4 Tm4) M(x int, b byte) (byte, int) { return b, x + 40 }
|
|
|
|
|
|
|
|
func TestMethod5(t *testing.T) {
|
|
|
|
CheckF := func(name string, f func(int, byte) (byte, int), inc int) {
|
|
|
|
b, x := f(1000, 99)
|
|
|
|
if b != 99 || x != 1000+inc {
|
|
|
|
t.Errorf("%s(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckV := func(name string, i Value, inc int) {
|
|
|
|
bx := i.Method(0).Call([]Value{ValueOf(1000), ValueOf(byte(99))})
|
|
|
|
b := bx[0].Interface()
|
|
|
|
x := bx[1].Interface()
|
|
|
|
if b != byte(99) || x != 1000+inc {
|
|
|
|
t.Errorf("direct %s.M(1000, 99) = %v, %v, want 99, %v", name, b, x, 1000+inc)
|
|
|
|
}
|
|
|
|
|
|
|
|
CheckF(name+".M", i.Method(0).Interface().(func(int, byte) (byte, int)), inc)
|
|
|
|
}
|
|
|
|
|
|
|
|
var TinterType = TypeOf(new(Tinter)).Elem()
|
|
|
|
var tinterType = TypeOf(new(tinter)).Elem()
|
|
|
|
|
|
|
|
CheckI := func(name string, i interface{}, inc int) {
|
|
|
|
v := ValueOf(i)
|
|
|
|
CheckV(name, v, inc)
|
|
|
|
CheckV("(i="+name+")", v.Convert(TinterType), inc)
|
|
|
|
}
|
|
|
|
|
|
|
|
sv := Tsmallv(1)
|
|
|
|
CheckI("sv", sv, 1)
|
|
|
|
CheckI("&sv", &sv, 1)
|
|
|
|
|
|
|
|
sp := Tsmallp(2)
|
|
|
|
CheckI("&sp", &sp, 2)
|
|
|
|
|
|
|
|
wv := Twordv(3)
|
|
|
|
CheckI("wv", wv, 3)
|
|
|
|
CheckI("&wv", &wv, 3)
|
|
|
|
|
|
|
|
wp := Twordp(4)
|
|
|
|
CheckI("&wp", &wp, 4)
|
|
|
|
|
|
|
|
bv := Tbigv([2]uintptr{5, 6})
|
|
|
|
CheckI("bv", bv, 11)
|
|
|
|
CheckI("&bv", &bv, 11)
|
|
|
|
|
|
|
|
bp := Tbigp([2]uintptr{7, 8})
|
|
|
|
CheckI("&bp", &bp, 15)
|
|
|
|
|
|
|
|
t4 := Tm4{}
|
|
|
|
t3 := Tm3{&t4}
|
|
|
|
t2 := Tm2{&t3}
|
|
|
|
t1 := Tm1{t2}
|
|
|
|
CheckI("t4", t4, 40)
|
|
|
|
CheckI("&t4", &t4, 40)
|
|
|
|
CheckI("t3", t3, 40)
|
|
|
|
CheckI("&t3", &t3, 40)
|
|
|
|
CheckI("t2", t2, 40)
|
|
|
|
CheckI("&t2", &t2, 40)
|
|
|
|
CheckI("t1", t1, 40)
|
|
|
|
CheckI("&t1", &t1, 40)
|
|
|
|
|
|
|
|
methodShouldPanic := func(name string, i interface{}) {
|
|
|
|
v := ValueOf(i)
|
|
|
|
m := v.Method(0)
|
|
|
|
shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
|
|
|
|
shouldPanic(func() { m.Interface() })
|
|
|
|
|
|
|
|
v = v.Convert(tinterType)
|
|
|
|
m = v.Method(0)
|
|
|
|
shouldPanic(func() { m.Call([]Value{ValueOf(1000), ValueOf(byte(99))}) })
|
|
|
|
shouldPanic(func() { m.Interface() })
|
|
|
|
}
|
|
|
|
|
|
|
|
_sv := tsmallv(1)
|
|
|
|
methodShouldPanic("_sv", _sv)
|
|
|
|
methodShouldPanic("&_sv", &_sv)
|
|
|
|
|
|
|
|
_sp := tsmallp(2)
|
|
|
|
methodShouldPanic("&_sp", &_sp)
|
|
|
|
|
|
|
|
_wv := twordv(3)
|
|
|
|
methodShouldPanic("_wv", _wv)
|
|
|
|
methodShouldPanic("&_wv", &_wv)
|
|
|
|
|
|
|
|
_wp := twordp(4)
|
|
|
|
methodShouldPanic("&_wp", &_wp)
|
|
|
|
|
|
|
|
_bv := tbigv([2]uintptr{5, 6})
|
|
|
|
methodShouldPanic("_bv", _bv)
|
|
|
|
methodShouldPanic("&_bv", &_bv)
|
|
|
|
|
|
|
|
_bp := tbigp([2]uintptr{7, 8})
|
|
|
|
methodShouldPanic("&_bp", &_bp)
|
|
|
|
|
|
|
|
var tnil Tinter
|
|
|
|
vnil := ValueOf(&tnil).Elem()
|
|
|
|
shouldPanic(func() { vnil.Method(0) })
|
|
|
|
}
|
|
|
|
|
2009-07-10 17:32:26 -06:00
|
|
|
func TestInterfaceSet(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
p := &Point{3, 4}
|
2009-07-10 17:32:26 -06:00
|
|
|
|
|
|
|
var s struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
I interface{}
|
|
|
|
P interface {
|
|
|
|
Dist(int) int
|
|
|
|
}
|
2009-07-10 17:32:26 -06:00
|
|
|
}
|
2011-04-25 11:39:16 -06:00
|
|
|
sv := ValueOf(&s).Elem()
|
|
|
|
sv.Field(0).Set(ValueOf(p))
|
2009-07-10 17:32:26 -06:00
|
|
|
if q := s.I.(*Point); q != p {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("i: have %p want %p", q, p)
|
2009-07-10 17:32:26 -06:00
|
|
|
}
|
|
|
|
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
pv := sv.Field(1)
|
2011-04-25 11:39:16 -06:00
|
|
|
pv.Set(ValueOf(p))
|
2009-07-10 17:32:26 -06:00
|
|
|
if q := s.P.(*Point); q != p {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("i: have %p want %p", q, p)
|
2009-07-10 17:32:26 -06:00
|
|
|
}
|
2009-08-12 14:18:37 -06:00
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
i := pv.Method(0).Call([]Value{ValueOf(10)})[0].Int()
|
2009-07-10 17:32:26 -06:00
|
|
|
if i != 250 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("Interface Method returned %d; want 250", i)
|
2009-07-10 17:32:26 -06:00
|
|
|
}
|
|
|
|
}
|
2009-08-05 16:56:44 -06:00
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
type T1 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
a string
|
|
|
|
int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
2009-08-05 16:56:44 -06:00
|
|
|
|
|
|
|
func TestAnonymousFields(t *testing.T) {
|
2009-12-15 16:40:16 -07:00
|
|
|
var field StructField
|
|
|
|
var ok bool
|
|
|
|
var t1 T1
|
2011-04-25 11:39:16 -06:00
|
|
|
type1 := TypeOf(t1)
|
2009-08-05 16:56:44 -06:00
|
|
|
if field, ok = type1.FieldByName("int"); !ok {
|
2012-09-05 07:35:53 -06:00
|
|
|
t.Fatal("no field 'int'")
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
if field.Index[0] != 1 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Error("field index should be 1; is", field.Index)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type FTest struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
s interface{}
|
|
|
|
name string
|
|
|
|
index []int
|
|
|
|
value int
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
2009-08-24 18:04:12 -06:00
|
|
|
type D1 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
d int
|
2009-08-24 18:04:12 -06:00
|
|
|
}
|
|
|
|
type D2 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
d int
|
2009-08-24 18:04:12 -06:00
|
|
|
}
|
|
|
|
|
2009-08-05 16:56:44 -06:00
|
|
|
type S0 struct {
|
2011-10-17 16:48:45 -06:00
|
|
|
A, B, C int
|
2009-12-15 16:40:16 -07:00
|
|
|
D1
|
|
|
|
D2
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type S1 struct {
|
2011-10-17 16:48:45 -06:00
|
|
|
B int
|
2009-12-15 16:40:16 -07:00
|
|
|
S0
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type S2 struct {
|
2011-10-17 16:48:45 -06:00
|
|
|
A int
|
2009-12-15 16:40:16 -07:00
|
|
|
*S1
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
2009-08-24 18:04:12 -06:00
|
|
|
type S1x struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
S1
|
2009-08-24 18:04:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type S1y struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
S1
|
2009-08-24 18:04:12 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type S3 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
S1x
|
|
|
|
S2
|
2011-10-17 16:48:45 -06:00
|
|
|
D, E int
|
2009-12-15 16:40:16 -07:00
|
|
|
*S1y
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
type S4 struct {
|
2009-12-15 16:40:16 -07:00
|
|
|
*S4
|
2011-10-17 16:48:45 -06:00
|
|
|
A int
|
2009-11-05 15:23:20 -07:00
|
|
|
}
|
|
|
|
|
2012-09-05 07:35:53 -06:00
|
|
|
// The X in S6 and S7 annihilate, but they also block the X in S8.S9.
|
|
|
|
type S5 struct {
|
|
|
|
S6
|
|
|
|
S7
|
|
|
|
S8
|
|
|
|
}
|
|
|
|
|
|
|
|
type S6 struct {
|
|
|
|
X int
|
|
|
|
}
|
|
|
|
|
|
|
|
type S7 S6
|
|
|
|
|
|
|
|
type S8 struct {
|
|
|
|
S9
|
|
|
|
}
|
|
|
|
|
|
|
|
type S9 struct {
|
|
|
|
X int
|
|
|
|
Y int
|
|
|
|
}
|
|
|
|
|
|
|
|
// The X in S11.S6 and S12.S6 annihilate, but they also block the X in S13.S8.S9.
|
|
|
|
type S10 struct {
|
|
|
|
S11
|
|
|
|
S12
|
|
|
|
S13
|
|
|
|
}
|
|
|
|
|
|
|
|
type S11 struct {
|
|
|
|
S6
|
|
|
|
}
|
|
|
|
|
|
|
|
type S12 struct {
|
|
|
|
S6
|
|
|
|
}
|
|
|
|
|
|
|
|
type S13 struct {
|
|
|
|
S8
|
|
|
|
}
|
|
|
|
|
2012-11-13 11:45:30 -07:00
|
|
|
// The X in S15.S11.S1 and S16.S11.S1 annihilate.
|
|
|
|
type S14 struct {
|
|
|
|
S15
|
|
|
|
S16
|
|
|
|
}
|
|
|
|
|
|
|
|
type S15 struct {
|
|
|
|
S11
|
|
|
|
}
|
|
|
|
|
|
|
|
type S16 struct {
|
|
|
|
S11
|
|
|
|
}
|
|
|
|
|
2009-11-05 15:23:20 -07:00
|
|
|
var fieldTests = []FTest{
|
2010-10-22 11:06:33 -06:00
|
|
|
{struct{}{}, "", nil, 0},
|
2011-10-17 16:48:45 -06:00
|
|
|
{struct{}{}, "Foo", nil, 0},
|
|
|
|
{S0{A: 'a'}, "A", []int{0}, 'a'},
|
|
|
|
{S0{}, "D", nil, 0},
|
|
|
|
{S1{S0: S0{A: 'a'}}, "A", []int{1, 0}, 'a'},
|
|
|
|
{S1{B: 'b'}, "B", []int{0}, 'b'},
|
2010-10-22 11:06:33 -06:00
|
|
|
{S1{}, "S0", []int{1}, 0},
|
2011-10-17 16:48:45 -06:00
|
|
|
{S1{S0: S0{C: 'c'}}, "C", []int{1, 2}, 'c'},
|
|
|
|
{S2{A: 'a'}, "A", []int{0}, 'a'},
|
2010-10-22 11:06:33 -06:00
|
|
|
{S2{}, "S1", []int{1}, 0},
|
2011-10-17 16:48:45 -06:00
|
|
|
{S2{S1: &S1{B: 'b'}}, "B", []int{1, 0}, 'b'},
|
|
|
|
{S2{S1: &S1{S0: S0{C: 'c'}}}, "C", []int{1, 1, 2}, 'c'},
|
|
|
|
{S2{}, "D", nil, 0},
|
2010-10-22 11:06:33 -06:00
|
|
|
{S3{}, "S1", nil, 0},
|
2011-10-17 16:48:45 -06:00
|
|
|
{S3{S2: S2{A: 'a'}}, "A", []int{1, 0}, 'a'},
|
|
|
|
{S3{}, "B", nil, 0},
|
|
|
|
{S3{D: 'd'}, "D", []int{2}, 0},
|
|
|
|
{S3{E: 'e'}, "E", []int{3}, 'e'},
|
|
|
|
{S4{A: 'a'}, "A", []int{1}, 'a'},
|
|
|
|
{S4{}, "B", nil, 0},
|
2012-09-05 07:35:53 -06:00
|
|
|
{S5{}, "X", nil, 0},
|
|
|
|
{S5{}, "Y", []int{2, 0, 1}, 0},
|
|
|
|
{S10{}, "X", nil, 0},
|
|
|
|
{S10{}, "Y", []int{2, 0, 0, 1}, 0},
|
2012-11-13 11:45:30 -07:00
|
|
|
{S14{}, "X", nil, 0},
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestFieldByIndex(t *testing.T) {
|
|
|
|
for _, test := range fieldTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
s := TypeOf(test.s)
|
2009-12-15 16:40:16 -07:00
|
|
|
f := s.FieldByIndex(test.index)
|
2009-08-05 16:56:44 -06:00
|
|
|
if f.Name != "" {
|
|
|
|
if test.index != nil {
|
|
|
|
if f.Name != test.name {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s found; want %s", s.Name(), f.Name, test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s found", s.Name(), f.Name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else if len(test.index) > 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s not found", s.Name(), test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if test.value != 0 {
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(test.s).FieldByIndex(test.index)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if v.IsValid() {
|
2009-08-05 16:56:44 -06:00
|
|
|
if x, ok := v.Interface().(int); ok {
|
|
|
|
if x != test.value {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s%v is %d; want %d", s.Name(), test.index, x, test.value)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s%v value not an int", s.Name(), test.index)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s%v value not found", s.Name(), test.index)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestFieldByName(t *testing.T) {
|
|
|
|
for _, test := range fieldTests {
|
2011-04-25 11:39:16 -06:00
|
|
|
s := TypeOf(test.s)
|
2009-12-15 16:40:16 -07:00
|
|
|
f, found := s.FieldByName(test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
if found {
|
|
|
|
if test.index != nil {
|
|
|
|
// Verify field depth and index.
|
|
|
|
if len(f.Index) != len(test.index) {
|
2012-09-05 07:35:53 -06:00
|
|
|
t.Errorf("%s.%s depth %d; want %d: %v vs %v", s.Name(), test.name, len(f.Index), len(test.index), f.Index, test.index)
|
2009-08-05 16:56:44 -06:00
|
|
|
} else {
|
|
|
|
for i, x := range f.Index {
|
|
|
|
if x != test.index[i] {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s.Index[%d] is %d; want %d", s.Name(), test.name, i, x, test.index[i])
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s found", s.Name(), f.Name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else if len(test.index) > 0 {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s not found", s.Name(), test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
2009-08-12 14:18:37 -06:00
|
|
|
|
2009-08-05 16:56:44 -06:00
|
|
|
if test.value != 0 {
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(test.s).FieldByName(test.name)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
if v.IsValid() {
|
2009-08-05 16:56:44 -06:00
|
|
|
if x, ok := v.Interface().(int); ok {
|
|
|
|
if x != test.value {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s is %d; want %d", s.Name(), test.name, x, test.value)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s value not an int", s.Name(), test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
} else {
|
2009-11-09 13:07:39 -07:00
|
|
|
t.Errorf("%s.%s value not found", s.Name(), test.name)
|
2009-08-05 16:56:44 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-01-25 00:33:59 -07:00
|
|
|
|
|
|
|
func TestImportPath(t *testing.T) {
|
2012-01-19 15:26:17 -07:00
|
|
|
tests := []struct {
|
|
|
|
t Type
|
|
|
|
path string
|
|
|
|
}{
|
|
|
|
{TypeOf(&base64.Encoding{}).Elem(), "encoding/base64"},
|
2012-09-01 17:55:55 -06:00
|
|
|
{TypeOf(int(0)), ""},
|
|
|
|
{TypeOf(int8(0)), ""},
|
|
|
|
{TypeOf(int16(0)), ""},
|
|
|
|
{TypeOf(int32(0)), ""},
|
|
|
|
{TypeOf(int64(0)), ""},
|
2012-01-19 15:26:17 -07:00
|
|
|
{TypeOf(uint(0)), ""},
|
2012-09-01 17:55:55 -06:00
|
|
|
{TypeOf(uint8(0)), ""},
|
|
|
|
{TypeOf(uint16(0)), ""},
|
|
|
|
{TypeOf(uint32(0)), ""},
|
|
|
|
{TypeOf(uint64(0)), ""},
|
|
|
|
{TypeOf(uintptr(0)), ""},
|
|
|
|
{TypeOf(float32(0)), ""},
|
|
|
|
{TypeOf(float64(0)), ""},
|
|
|
|
{TypeOf(complex64(0)), ""},
|
|
|
|
{TypeOf(complex128(0)), ""},
|
|
|
|
{TypeOf(byte(0)), ""},
|
|
|
|
{TypeOf(rune(0)), ""},
|
|
|
|
{TypeOf([]byte(nil)), ""},
|
|
|
|
{TypeOf([]rune(nil)), ""},
|
|
|
|
{TypeOf(string("")), ""},
|
|
|
|
{TypeOf((*interface{})(nil)).Elem(), ""},
|
|
|
|
{TypeOf((*byte)(nil)), ""},
|
|
|
|
{TypeOf((*rune)(nil)), ""},
|
|
|
|
{TypeOf((*int64)(nil)), ""},
|
2012-01-19 15:26:17 -07:00
|
|
|
{TypeOf(map[string]int{}), ""},
|
|
|
|
{TypeOf((*error)(nil)).Elem(), ""},
|
|
|
|
}
|
|
|
|
for _, test := range tests {
|
|
|
|
if path := test.t.PkgPath(); path != test.path {
|
|
|
|
t.Errorf("%v.PkgPath() = %q, want %q", test.t, path, test.path)
|
|
|
|
}
|
2010-01-25 00:33:59 -07:00
|
|
|
}
|
|
|
|
}
|
2010-06-14 12:23:11 -06:00
|
|
|
|
2011-07-26 21:44:57 -06:00
|
|
|
func TestVariadicType(t *testing.T) {
|
2011-07-26 21:29:44 -06:00
|
|
|
// Test example from Type documentation.
|
2011-01-19 21:09:00 -07:00
|
|
|
var f func(x int, y ...float64)
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf(f)
|
|
|
|
if typ.NumIn() == 2 && typ.In(0) == TypeOf(int(0)) {
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
sl := typ.In(1)
|
|
|
|
if sl.Kind() == Slice {
|
2011-04-25 11:39:16 -06:00
|
|
|
if sl.Elem() == TypeOf(0.0) {
|
2010-06-14 12:23:11 -06:00
|
|
|
// ok
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Failed
|
2011-01-19 21:09:00 -07:00
|
|
|
t.Errorf("want NumIn() = 2, In(0) = int, In(1) = []float64")
|
2010-06-14 12:23:11 -06:00
|
|
|
s := fmt.Sprintf("have NumIn() = %d", typ.NumIn())
|
|
|
|
for i := 0; i < typ.NumIn(); i++ {
|
|
|
|
s += fmt.Sprintf(", In(%d) = %s", i, typ.In(i))
|
|
|
|
}
|
|
|
|
t.Error(s)
|
|
|
|
}
|
2010-09-27 12:09:10 -06:00
|
|
|
|
2010-09-28 11:43:50 -06:00
|
|
|
type inner struct {
|
|
|
|
x int
|
|
|
|
}
|
2010-09-27 12:09:10 -06:00
|
|
|
|
|
|
|
type outer struct {
|
2010-09-28 11:43:50 -06:00
|
|
|
y int
|
2010-09-27 12:09:10 -06:00
|
|
|
inner
|
|
|
|
}
|
|
|
|
|
|
|
|
func (*inner) m() {}
|
|
|
|
func (*outer) m() {}
|
|
|
|
|
|
|
|
func TestNestedMethods(t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf((*outer)(nil))
|
|
|
|
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*outer).m).Pointer() {
|
2010-09-27 12:09:10 -06:00
|
|
|
t.Errorf("Wrong method table for outer: (m=%p)", (*outer).m)
|
|
|
|
for i := 0; i < typ.NumMethod(); i++ {
|
|
|
|
m := typ.Method(i)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
|
2010-09-27 12:09:10 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2010-09-28 11:43:50 -06:00
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
type InnerInt struct {
|
|
|
|
X int
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
type OuterInt struct {
|
|
|
|
Y int
|
|
|
|
InnerInt
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
func (i *InnerInt) M() int {
|
|
|
|
return i.X
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestEmbeddedMethods(t *testing.T) {
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf((*OuterInt)(nil))
|
|
|
|
if typ.NumMethod() != 1 || typ.Method(0).Func.Pointer() != ValueOf((*OuterInt).M).Pointer() {
|
2011-04-21 06:14:50 -06:00
|
|
|
t.Errorf("Wrong method table for OuterInt: (m=%p)", (*OuterInt).M)
|
2010-09-28 11:43:50 -06:00
|
|
|
for i := 0; i < typ.NumMethod(); i++ {
|
|
|
|
m := typ.Method(i)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
t.Errorf("\t%d: %s %#x\n", i, m.Name, m.Func.Pointer())
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
i := &InnerInt{3}
|
2011-04-25 11:39:16 -06:00
|
|
|
if v := ValueOf(i).Method(0).Call(nil)[0].Int(); v != 3 {
|
2011-04-21 06:14:50 -06:00
|
|
|
t.Errorf("i.M() = %d, want 3", v)
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
o := &OuterInt{1, InnerInt{2}}
|
2011-04-25 11:39:16 -06:00
|
|
|
if v := ValueOf(o).Method(0).Call(nil)[0].Int(); v != 2 {
|
2011-04-21 06:14:50 -06:00
|
|
|
t.Errorf("i.M() = %d, want 2", v)
|
2010-09-28 11:43:50 -06:00
|
|
|
}
|
|
|
|
|
2011-04-21 06:14:50 -06:00
|
|
|
f := (*OuterInt).M
|
2010-09-28 11:43:50 -06:00
|
|
|
if v := f(o); v != 2 {
|
|
|
|
t.Errorf("f(o) = %d, want 2", v)
|
|
|
|
}
|
|
|
|
}
|
2011-03-03 11:20:17 -07:00
|
|
|
|
|
|
|
func TestPtrTo(t *testing.T) {
|
|
|
|
var i int
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
typ := TypeOf(i)
|
2011-03-03 11:20:17 -07:00
|
|
|
for i = 0; i < 100; i++ {
|
|
|
|
typ = PtrTo(typ)
|
|
|
|
}
|
|
|
|
for i = 0; i < 100; i++ {
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
typ = typ.Elem()
|
2011-03-03 11:20:17 -07:00
|
|
|
}
|
2011-04-25 11:39:16 -06:00
|
|
|
if typ != TypeOf(i) {
|
|
|
|
t.Errorf("after 100 PtrTo and Elem, have %s, want %s", typ, TypeOf(i))
|
2011-03-03 11:20:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-03-26 12:50:29 -06:00
|
|
|
func TestPtrToGC(t *testing.T) {
|
|
|
|
type T *uintptr
|
|
|
|
tt := TypeOf(T(nil))
|
|
|
|
pt := PtrTo(tt)
|
|
|
|
const n = 100
|
|
|
|
var x []interface{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v := New(pt)
|
|
|
|
p := new(*uintptr)
|
|
|
|
*p = new(uintptr)
|
|
|
|
**p = uintptr(i)
|
|
|
|
v.Elem().Set(ValueOf(p).Convert(pt))
|
|
|
|
x = append(x, v.Interface())
|
|
|
|
}
|
|
|
|
runtime.GC()
|
|
|
|
|
|
|
|
for i, xi := range x {
|
|
|
|
k := ValueOf(xi).Elem().Elem().Elem().Interface().(uintptr)
|
|
|
|
if k != uintptr(i) {
|
|
|
|
t.Errorf("lost x[%d] = %d, want %d", i, k, i)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-03 11:20:17 -07:00
|
|
|
func TestAddr(t *testing.T) {
|
|
|
|
var p struct {
|
|
|
|
X, Y int
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(&p)
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v = v.Elem()
|
2011-03-03 11:20:17 -07:00
|
|
|
v = v.Addr()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v = v.Elem()
|
|
|
|
v = v.Field(0)
|
|
|
|
v.SetInt(2)
|
2011-03-03 11:20:17 -07:00
|
|
|
if p.X != 2 {
|
|
|
|
t.Errorf("Addr.Elem.Set failed to set value")
|
|
|
|
}
|
|
|
|
|
2011-04-25 11:39:16 -06:00
|
|
|
// Again but take address of the ValueOf value.
|
2011-03-03 11:20:17 -07:00
|
|
|
// Exercises generation of PtrTypes not present in the binary.
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
q := &p
|
2011-04-25 11:39:16 -06:00
|
|
|
v = ValueOf(&q).Elem()
|
2011-03-03 11:20:17 -07:00
|
|
|
v = v.Addr()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v = v.Elem()
|
|
|
|
v = v.Elem()
|
2011-03-03 11:20:17 -07:00
|
|
|
v = v.Addr()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v = v.Elem()
|
|
|
|
v = v.Field(0)
|
|
|
|
v.SetInt(3)
|
2011-03-03 11:20:17 -07:00
|
|
|
if p.X != 3 {
|
|
|
|
t.Errorf("Addr.Elem.Set failed to set value")
|
|
|
|
}
|
|
|
|
|
|
|
|
// Starting without pointer we should get changed value
|
|
|
|
// in interface.
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
qq := p
|
2011-04-25 11:39:16 -06:00
|
|
|
v = ValueOf(&qq).Elem()
|
2011-03-03 11:20:17 -07:00
|
|
|
v0 := v
|
|
|
|
v = v.Addr()
|
reflect: new Type and Value definitions
Type is now an interface that implements all the possible type methods.
Instead of a type switch on a reflect.Type t, switch on t.Kind().
If a method is invoked on the wrong kind of type (for example,
calling t.Field(0) when t.Kind() != Struct), the call panics.
There is one method renaming: t.(*ChanType).Dir() is now t.ChanDir().
Value is now a struct value that implements all the possible value methods.
Instead of a type switch on a reflect.Value v, switch on v.Kind().
If a method is invoked on the wrong kind of value (for example,
calling t.Recv() when t.Kind() != Chan), the call panics.
Since Value is now a struct, not an interface, its zero value
cannot be compared to nil. Instead of v != nil, use v.IsValid().
Instead of other uses of nil as a Value, use Value{}, the zero value.
Many methods have been renamed, most due to signature conflicts:
OLD NEW
v.(*ArrayValue).Elem v.Index
v.(*BoolValue).Get v.Bool
v.(*BoolValue).Set v.SetBool
v.(*ChanType).Dir v.ChanDir
v.(*ChanValue).Get v.Pointer
v.(*ComplexValue).Get v.Complex
v.(*ComplexValue).Overflow v.OverflowComplex
v.(*ComplexValue).Set v.SetComplex
v.(*FloatValue).Get v.Float
v.(*FloatValue).Overflow v.OverflowFloat
v.(*FloatValue).Set v.SetFloat
v.(*FuncValue).Get v.Pointer
v.(*InterfaceValue).Get v.InterfaceData
v.(*IntValue).Get v.Int
v.(*IntValue).Overflow v.OverflowInt
v.(*IntValue).Set v.SetInt
v.(*MapValue).Elem v.MapIndex
v.(*MapValue).Get v.Pointer
v.(*MapValue).Keys v.MapKeys
v.(*MapValue).SetElem v.SetMapIndex
v.(*PtrValue).Get v.Pointer
v.(*SliceValue).Elem v.Index
v.(*SliceValue).Get v.Pointer
v.(*StringValue).Get v.String
v.(*StringValue).Set v.SetString
v.(*UintValue).Get v.Uint
v.(*UintValue).Overflow v.OverflowUint
v.(*UintValue).Set v.SetUint
v.(*UnsafePointerValue).Get v.Pointer
v.(*UnsafePointerValue).Set v.SetPointer
Part of the motivation for this change is to enable a more
efficient implementation of Value, one that does not allocate
memory during most operations. To reduce the size of the CL,
this CL's implementation is a wrapper around the old API.
Later CLs will make the implementation more efficient without
changing the API.
Other CLs to be submitted at the same time as this one
add support for this change to gofix (4343047) and update
the Go source tree (4353043).
R=gri, iant, niemeyer, r, rog, gustavo, r2
CC=golang-dev
https://golang.org/cl/4281055
2011-04-08 10:26:51 -06:00
|
|
|
v = v.Elem()
|
|
|
|
v = v.Field(0)
|
|
|
|
v.SetInt(4)
|
2011-03-03 11:20:17 -07:00
|
|
|
if p.X != 3 { // should be unchanged from last time
|
|
|
|
t.Errorf("somehow value Set changed original p")
|
|
|
|
}
|
|
|
|
p = v0.Interface().(struct {
|
|
|
|
X, Y int
|
|
|
|
})
|
|
|
|
if p.X != 4 {
|
|
|
|
t.Errorf("Addr.Elem.Set valued to set value in top value")
|
|
|
|
}
|
2012-02-03 18:36:25 -07:00
|
|
|
|
|
|
|
// Verify that taking the address of a type gives us a pointer
|
|
|
|
// which we can convert back using the usual interface
|
|
|
|
// notation.
|
|
|
|
var s struct {
|
|
|
|
B *bool
|
|
|
|
}
|
|
|
|
ps := ValueOf(&s).Elem().Field(0).Addr().Interface()
|
|
|
|
*(ps.(**bool)) = new(bool)
|
|
|
|
if s.B == nil {
|
|
|
|
t.Errorf("Addr.Interface direct assignment failed")
|
|
|
|
}
|
2011-03-03 11:20:17 -07:00
|
|
|
}
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
|
|
|
|
func noAlloc(t *testing.T, n int, f func(int)) {
|
2013-08-20 22:00:45 -06:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping malloc count in short mode")
|
|
|
|
}
|
2013-03-06 16:52:32 -07:00
|
|
|
if runtime.GOMAXPROCS(0) > 1 {
|
|
|
|
t.Skip("skipping; GOMAXPROCS>1")
|
|
|
|
}
|
2013-02-02 20:52:29 -07:00
|
|
|
i := -1
|
|
|
|
allocs := testing.AllocsPerRun(n, func() {
|
|
|
|
f(i)
|
|
|
|
i++
|
|
|
|
})
|
|
|
|
if allocs > 0 {
|
|
|
|
t.Errorf("%d iterations: got %v mallocs, want 0", n, allocs)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAllocations(t *testing.T) {
|
|
|
|
noAlloc(t, 100, func(j int) {
|
|
|
|
var i interface{}
|
|
|
|
var v Value
|
|
|
|
i = 42 + j
|
2011-04-25 11:39:16 -06:00
|
|
|
v = ValueOf(i)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
if int(v.Int()) != 42+j {
|
|
|
|
panic("wrong int")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSmallNegativeInt(t *testing.T) {
|
|
|
|
i := int16(-1)
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(i)
|
reflect: more efficient; cannot Set result of NewValue anymore
* Reduces malloc counts during gob encoder/decoder test from 6/6 to 3/5.
The current reflect uses Set to mean two subtly different things.
(1) If you have a reflect.Value v, it might just represent
itself (as in v = reflect.NewValue(42)), in which case calling
v.Set only changed v, not any other data in the program.
(2) If you have a reflect Value v derived from a pointer
or a slice (as in x := []int{42}; v = reflect.NewValue(x).Index(0)),
v represents the value held there. Changing x[0] affects the
value returned by v.Int(), and calling v.Set affects x[0].
This was not really by design; it just happened that way.
The motivation for the new reflect implementation was
to remove mallocs. The use case (1) has an implicit malloc
inside it. If you can do:
v := reflect.NewValue(0)
v.Set(42)
i := v.Int() // i = 42
then that implies that v is referring to some underlying
chunk of memory in order to remember the 42; that is,
NewValue must have allocated some memory.
Almost all the time you are using reflect the goal is to
inspect or to change other data, not to manipulate data
stored solely inside a reflect.Value.
This CL removes use case (1), so that an assignable
reflect.Value must always refer to some other piece of data
in the program. Put another way, removing this case would
make
v := reflect.NewValue(0)
v.Set(42)
as illegal as
0 = 42.
It would also make this illegal:
x := 0
v := reflect.NewValue(x)
v.Set(42)
for the same reason. (Note that right now, v.Set(42) "succeeds"
but does not change the value of x.)
If you really wanted to make v refer to x, you'd start with &x
and dereference it:
x := 0
v := reflect.NewValue(&x).Elem() // v = *&x
v.Set(42)
It's pretty rare, except in tests, to want to use NewValue and then
call Set to change the Value itself instead of some other piece of
data in the program. I haven't seen it happen once yet while
making the tree build with this change.
For the same reasons, reflect.Zero (formerly reflect.MakeZero)
would also return an unassignable, unaddressable value.
This invalidates the (awkward) idiom:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.PointTo(v)
which, when the API changed, turned into:
pv := ... some Ptr Value we have ...
v := reflect.Zero(pv.Type().Elem())
pv.Set(v.Addr())
In both, it is far from clear what the code is trying to do. Now that
it is possible, this CL adds reflect.New(Type) Value that does the
obvious thing (same as Go's new), so this code would be replaced by:
pv := ... some Ptr Value we have ...
pv.Set(reflect.New(pv.Type().Elem()))
The changes just described can be confusing to think about,
but I believe it is because the old API was confusing - it was
conflating two different kinds of Values - and that the new API
by itself is pretty simple: you can only Set (or call Addr on)
a Value if it actually addresses some real piece of data; that is,
only if it is the result of dereferencing a Ptr or indexing a Slice.
If you really want the old behavior, you'd get it by translating:
v := reflect.NewValue(x)
into
v := reflect.New(reflect.Typeof(x)).Elem()
v.Set(reflect.NewValue(x))
Gofix will not be able to help with this, because whether
and how to change the code depends on whether the original
code meant use (1) or use (2), so the developer has to read
and think about the code.
You can see the effect on packages in the tree in
https://golang.org/cl/4423043/.
R=r
CC=golang-dev
https://golang.org/cl/4435042
2011-04-18 12:35:33 -06:00
|
|
|
if v.Int() != -1 {
|
|
|
|
t.Errorf("int16(-1).Int() returned %v", v.Int())
|
|
|
|
}
|
|
|
|
}
|
2011-04-18 18:00:42 -06:00
|
|
|
|
2012-10-21 15:02:10 -06:00
|
|
|
func TestIndex(t *testing.T) {
|
|
|
|
xs := []byte{1, 2, 3, 4, 5, 6, 7, 8}
|
|
|
|
v := ValueOf(xs).Index(3).Interface().(byte)
|
|
|
|
if v != xs[3] {
|
|
|
|
t.Errorf("xs.Index(3) = %v; expected %v", v, xs[3])
|
|
|
|
}
|
|
|
|
xa := [8]byte{10, 20, 30, 40, 50, 60, 70, 80}
|
|
|
|
v = ValueOf(xa).Index(2).Interface().(byte)
|
|
|
|
if v != xa[2] {
|
|
|
|
t.Errorf("xa.Index(2) = %v; expected %v", v, xa[2])
|
|
|
|
}
|
|
|
|
s := "0123456789"
|
|
|
|
v = ValueOf(s).Index(3).Interface().(byte)
|
|
|
|
if v != s[3] {
|
|
|
|
t.Errorf("s.Index(3) = %v; expected %v", v, s[3])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-04-18 18:00:42 -06:00
|
|
|
func TestSlice(t *testing.T) {
|
|
|
|
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
2011-04-25 11:39:16 -06:00
|
|
|
v := ValueOf(xs).Slice(3, 5).Interface().([]int)
|
2011-12-12 14:45:40 -07:00
|
|
|
if len(v) != 2 {
|
|
|
|
t.Errorf("len(xs.Slice(3, 5)) = %d", len(v))
|
|
|
|
}
|
|
|
|
if cap(v) != 5 {
|
|
|
|
t.Errorf("cap(xs.Slice(3, 5)) = %d", cap(v))
|
|
|
|
}
|
|
|
|
if !DeepEqual(v[0:5], xs[3:]) {
|
|
|
|
t.Errorf("xs.Slice(3, 5)[0:5] = %v", v[0:5])
|
2011-04-18 18:00:42 -06:00
|
|
|
}
|
2011-12-12 14:45:40 -07:00
|
|
|
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
2011-04-25 11:39:16 -06:00
|
|
|
v = ValueOf(&xa).Elem().Slice(2, 5).Interface().([]int)
|
2011-12-12 14:45:40 -07:00
|
|
|
if len(v) != 3 {
|
|
|
|
t.Errorf("len(xa.Slice(2, 5)) = %d", len(v))
|
|
|
|
}
|
|
|
|
if cap(v) != 6 {
|
|
|
|
t.Errorf("cap(xa.Slice(2, 5)) = %d", cap(v))
|
|
|
|
}
|
|
|
|
if !DeepEqual(v[0:6], xa[2:]) {
|
|
|
|
t.Errorf("xs.Slice(2, 5)[0:6] = %v", v[0:6])
|
2011-04-18 18:00:42 -06:00
|
|
|
}
|
2012-10-21 15:02:10 -06:00
|
|
|
s := "0123456789"
|
|
|
|
vs := ValueOf(s).Slice(3, 5).Interface().(string)
|
|
|
|
if vs != s[3:5] {
|
|
|
|
t.Errorf("s.Slice(3, 5) = %q; expected %q", vs, s[3:5])
|
|
|
|
}
|
2011-04-18 18:00:42 -06:00
|
|
|
}
|
2011-04-20 14:24:45 -06:00
|
|
|
|
2013-07-01 18:32:53 -06:00
|
|
|
func TestSlice3(t *testing.T) {
|
|
|
|
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
|
|
|
v := ValueOf(xs).Slice3(3, 5, 7).Interface().([]int)
|
|
|
|
if len(v) != 2 {
|
|
|
|
t.Errorf("len(xs.Slice3(3, 5, 7)) = %d", len(v))
|
|
|
|
}
|
|
|
|
if cap(v) != 4 {
|
|
|
|
t.Errorf("cap(xs.Slice3(3, 5, 7)) = %d", cap(v))
|
|
|
|
}
|
|
|
|
if !DeepEqual(v[0:4], xs[3:7:7]) {
|
|
|
|
t.Errorf("xs.Slice3(3, 5, 7)[0:4] = %v", v[0:4])
|
|
|
|
}
|
|
|
|
rv := ValueOf(&xs).Elem()
|
|
|
|
shouldPanic(func() { rv.Slice3(1, 2, 1) })
|
|
|
|
shouldPanic(func() { rv.Slice3(1, 1, 11) })
|
|
|
|
shouldPanic(func() { rv.Slice3(2, 2, 1) })
|
|
|
|
|
|
|
|
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
|
|
|
v = ValueOf(&xa).Elem().Slice3(2, 5, 6).Interface().([]int)
|
|
|
|
if len(v) != 3 {
|
|
|
|
t.Errorf("len(xa.Slice(2, 5, 6)) = %d", len(v))
|
|
|
|
}
|
|
|
|
if cap(v) != 4 {
|
|
|
|
t.Errorf("cap(xa.Slice(2, 5, 6)) = %d", cap(v))
|
|
|
|
}
|
|
|
|
if !DeepEqual(v[0:4], xa[2:6:6]) {
|
|
|
|
t.Errorf("xs.Slice(2, 5, 6)[0:4] = %v", v[0:4])
|
|
|
|
}
|
|
|
|
rv = ValueOf(&xa).Elem()
|
|
|
|
shouldPanic(func() { rv.Slice3(1, 2, 1) })
|
|
|
|
shouldPanic(func() { rv.Slice3(1, 1, 11) })
|
|
|
|
shouldPanic(func() { rv.Slice3(2, 2, 1) })
|
|
|
|
|
|
|
|
s := "hello world"
|
|
|
|
rv = ValueOf(&s).Elem()
|
|
|
|
shouldPanic(func() { rv.Slice3(1, 2, 3) })
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetLenCap(t *testing.T) {
|
|
|
|
xs := []int{1, 2, 3, 4, 5, 6, 7, 8}
|
|
|
|
xa := [8]int{10, 20, 30, 40, 50, 60, 70, 80}
|
|
|
|
|
|
|
|
vs := ValueOf(&xs).Elem()
|
|
|
|
shouldPanic(func() { vs.SetLen(10) })
|
|
|
|
shouldPanic(func() { vs.SetCap(10) })
|
|
|
|
shouldPanic(func() { vs.SetLen(-1) })
|
|
|
|
shouldPanic(func() { vs.SetCap(-1) })
|
|
|
|
shouldPanic(func() { vs.SetCap(6) }) // smaller than len
|
|
|
|
vs.SetLen(5)
|
|
|
|
if len(xs) != 5 || cap(xs) != 8 {
|
|
|
|
t.Errorf("after SetLen(5), len, cap = %d, %d, want 5, 8", len(xs), cap(xs))
|
|
|
|
}
|
|
|
|
vs.SetCap(6)
|
|
|
|
if len(xs) != 5 || cap(xs) != 6 {
|
|
|
|
t.Errorf("after SetCap(6), len, cap = %d, %d, want 5, 6", len(xs), cap(xs))
|
|
|
|
}
|
|
|
|
vs.SetCap(5)
|
|
|
|
if len(xs) != 5 || cap(xs) != 5 {
|
|
|
|
t.Errorf("after SetCap(5), len, cap = %d, %d, want 5, 5", len(xs), cap(xs))
|
|
|
|
}
|
|
|
|
shouldPanic(func() { vs.SetCap(4) }) // smaller than len
|
|
|
|
shouldPanic(func() { vs.SetLen(6) }) // bigger than cap
|
|
|
|
|
|
|
|
va := ValueOf(&xa).Elem()
|
|
|
|
shouldPanic(func() { va.SetLen(8) })
|
|
|
|
shouldPanic(func() { va.SetCap(8) })
|
|
|
|
}
|
|
|
|
|
2011-04-20 14:24:45 -06:00
|
|
|
func TestVariadic(t *testing.T) {
|
|
|
|
var b bytes.Buffer
|
2011-04-25 11:39:16 -06:00
|
|
|
V := ValueOf
|
2011-04-20 14:24:45 -06:00
|
|
|
|
|
|
|
b.Reset()
|
|
|
|
V(fmt.Fprintf).Call([]Value{V(&b), V("%s, %d world"), V("hello"), V(42)})
|
|
|
|
if b.String() != "hello, 42 world" {
|
|
|
|
t.Errorf("after Fprintf Call: %q != %q", b.String(), "hello 42 world")
|
|
|
|
}
|
|
|
|
|
|
|
|
b.Reset()
|
|
|
|
V(fmt.Fprintf).CallSlice([]Value{V(&b), V("%s, %d world"), V([]interface{}{"hello", 42})})
|
|
|
|
if b.String() != "hello, 42 world" {
|
|
|
|
t.Errorf("after Fprintf CallSlice: %q != %q", b.String(), "hello 42 world")
|
|
|
|
}
|
|
|
|
}
|
2011-06-29 07:52:34 -06:00
|
|
|
|
2013-10-03 14:23:02 -06:00
|
|
|
func TestFuncArg(t *testing.T) {
|
|
|
|
f1 := func(i int, f func(int) int) int { return f(i) }
|
|
|
|
f2 := func(i int) int { return i + 1 }
|
|
|
|
r := ValueOf(f1).Call([]Value{ValueOf(100), ValueOf(f2)})
|
|
|
|
if r[0].Int() != 101 {
|
|
|
|
t.Errorf("function returned %d, want 101", r[0].Int())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-29 07:52:34 -06:00
|
|
|
var tagGetTests = []struct {
|
|
|
|
Tag StructTag
|
|
|
|
Key string
|
|
|
|
Value string
|
|
|
|
}{
|
|
|
|
{`protobuf:"PB(1,2)"`, `protobuf`, `PB(1,2)`},
|
|
|
|
{`protobuf:"PB(1,2)"`, `foo`, ``},
|
|
|
|
{`protobuf:"PB(1,2)"`, `rotobuf`, ``},
|
|
|
|
{`protobuf:"PB(1,2)" json:"name"`, `json`, `name`},
|
|
|
|
{`protobuf:"PB(1,2)" json:"name"`, `protobuf`, `PB(1,2)`},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestTagGet(t *testing.T) {
|
|
|
|
for _, tt := range tagGetTests {
|
|
|
|
if v := tt.Tag.Get(tt.Key); v != tt.Value {
|
|
|
|
t.Errorf("StructTag(%#q).Get(%#q) = %#q, want %#q", tt.Tag, tt.Key, v, tt.Value)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-08-23 20:50:08 -06:00
|
|
|
|
|
|
|
func TestBytes(t *testing.T) {
|
|
|
|
type B []byte
|
|
|
|
x := B{1, 2, 3, 4}
|
|
|
|
y := ValueOf(x).Bytes()
|
|
|
|
if !bytes.Equal(x, y) {
|
|
|
|
t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
|
|
|
|
}
|
|
|
|
if &x[0] != &y[0] {
|
|
|
|
t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSetBytes(t *testing.T) {
|
|
|
|
type B []byte
|
|
|
|
var x B
|
|
|
|
y := []byte{1, 2, 3, 4}
|
|
|
|
ValueOf(&x).Elem().SetBytes(y)
|
|
|
|
if !bytes.Equal(x, y) {
|
|
|
|
t.Fatalf("ValueOf(%v).Bytes() = %v", x, y)
|
|
|
|
}
|
|
|
|
if &x[0] != &y[0] {
|
|
|
|
t.Errorf("ValueOf(%p).Bytes() = %p", &x[0], &y[0])
|
|
|
|
}
|
|
|
|
}
|
2011-10-17 16:48:45 -06:00
|
|
|
|
|
|
|
type Private struct {
|
|
|
|
x int
|
|
|
|
y **int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Private) m() {
|
|
|
|
}
|
|
|
|
|
|
|
|
type Public struct {
|
|
|
|
X int
|
|
|
|
Y **int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (p *Public) M() {
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestUnexported(t *testing.T) {
|
|
|
|
var pub Public
|
|
|
|
v := ValueOf(&pub)
|
|
|
|
isValid(v.Elem().Field(0))
|
|
|
|
isValid(v.Elem().Field(1))
|
|
|
|
isValid(v.Elem().FieldByName("X"))
|
|
|
|
isValid(v.Elem().FieldByName("Y"))
|
|
|
|
isValid(v.Type().Method(0).Func)
|
|
|
|
isNonNil(v.Elem().Field(0).Interface())
|
|
|
|
isNonNil(v.Elem().Field(1).Interface())
|
|
|
|
isNonNil(v.Elem().FieldByName("X").Interface())
|
|
|
|
isNonNil(v.Elem().FieldByName("Y").Interface())
|
|
|
|
isNonNil(v.Type().Method(0).Func.Interface())
|
|
|
|
|
|
|
|
var priv Private
|
|
|
|
v = ValueOf(&priv)
|
|
|
|
isValid(v.Elem().Field(0))
|
|
|
|
isValid(v.Elem().Field(1))
|
|
|
|
isValid(v.Elem().FieldByName("x"))
|
|
|
|
isValid(v.Elem().FieldByName("y"))
|
|
|
|
isValid(v.Type().Method(0).Func)
|
|
|
|
shouldPanic(func() { v.Elem().Field(0).Interface() })
|
|
|
|
shouldPanic(func() { v.Elem().Field(1).Interface() })
|
|
|
|
shouldPanic(func() { v.Elem().FieldByName("x").Interface() })
|
|
|
|
shouldPanic(func() { v.Elem().FieldByName("y").Interface() })
|
|
|
|
shouldPanic(func() { v.Type().Method(0).Func.Interface() })
|
|
|
|
}
|
|
|
|
|
|
|
|
func shouldPanic(f func()) {
|
|
|
|
defer func() {
|
|
|
|
if recover() == nil {
|
|
|
|
panic("did not panic")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
f()
|
|
|
|
}
|
|
|
|
|
|
|
|
func isNonNil(x interface{}) {
|
|
|
|
if x == nil {
|
|
|
|
panic("nil interface")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func isValid(v Value) {
|
|
|
|
if !v.IsValid() {
|
|
|
|
panic("zero Value")
|
|
|
|
}
|
|
|
|
}
|
2012-03-01 09:48:27 -07:00
|
|
|
|
|
|
|
func TestAlias(t *testing.T) {
|
|
|
|
x := string("hello")
|
|
|
|
v := ValueOf(&x).Elem()
|
|
|
|
oldvalue := v.Interface()
|
|
|
|
v.SetString("world")
|
|
|
|
newvalue := v.Interface()
|
|
|
|
|
|
|
|
if oldvalue != "hello" || newvalue != "world" {
|
|
|
|
t.Errorf("aliasing: old=%q new=%q, want hello, world", oldvalue, newvalue)
|
|
|
|
}
|
|
|
|
}
|
2012-09-05 07:35:53 -06:00
|
|
|
|
2012-09-22 06:52:27 -06:00
|
|
|
var V = ValueOf
|
|
|
|
|
|
|
|
func EmptyInterfaceV(x interface{}) Value {
|
|
|
|
return ValueOf(&x).Elem()
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReaderV(x io.Reader) Value {
|
|
|
|
return ValueOf(&x).Elem()
|
|
|
|
}
|
|
|
|
|
|
|
|
func ReadWriterV(x io.ReadWriter) Value {
|
|
|
|
return ValueOf(&x).Elem()
|
|
|
|
}
|
|
|
|
|
|
|
|
type Empty struct{}
|
|
|
|
type MyString string
|
|
|
|
type MyBytes []byte
|
|
|
|
type MyRunes []int32
|
|
|
|
type MyFunc func()
|
|
|
|
type MyByte byte
|
|
|
|
|
|
|
|
var convertTests = []struct {
|
|
|
|
in Value
|
|
|
|
out Value
|
|
|
|
}{
|
|
|
|
// numbers
|
|
|
|
/*
|
|
|
|
Edit .+1,/\*\//-1>cat >/tmp/x.go && go run /tmp/x.go
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import "fmt"
|
|
|
|
|
|
|
|
var numbers = []string{
|
|
|
|
"int8", "uint8", "int16", "uint16",
|
|
|
|
"int32", "uint32", "int64", "uint64",
|
|
|
|
"int", "uint", "uintptr",
|
|
|
|
"float32", "float64",
|
|
|
|
}
|
|
|
|
|
|
|
|
func main() {
|
|
|
|
// all pairs but in an unusual order,
|
|
|
|
// to emit all the int8, uint8 cases
|
|
|
|
// before n grows too big.
|
|
|
|
n := 1
|
|
|
|
for i, f := range numbers {
|
|
|
|
for _, g := range numbers[i:] {
|
|
|
|
fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", f, n, g, n)
|
|
|
|
n++
|
|
|
|
if f != g {
|
|
|
|
fmt.Printf("\t{V(%s(%d)), V(%s(%d))},\n", g, n, f, n)
|
|
|
|
n++
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
{V(int8(1)), V(int8(1))},
|
|
|
|
{V(int8(2)), V(uint8(2))},
|
|
|
|
{V(uint8(3)), V(int8(3))},
|
|
|
|
{V(int8(4)), V(int16(4))},
|
|
|
|
{V(int16(5)), V(int8(5))},
|
|
|
|
{V(int8(6)), V(uint16(6))},
|
|
|
|
{V(uint16(7)), V(int8(7))},
|
|
|
|
{V(int8(8)), V(int32(8))},
|
|
|
|
{V(int32(9)), V(int8(9))},
|
|
|
|
{V(int8(10)), V(uint32(10))},
|
|
|
|
{V(uint32(11)), V(int8(11))},
|
|
|
|
{V(int8(12)), V(int64(12))},
|
|
|
|
{V(int64(13)), V(int8(13))},
|
|
|
|
{V(int8(14)), V(uint64(14))},
|
|
|
|
{V(uint64(15)), V(int8(15))},
|
|
|
|
{V(int8(16)), V(int(16))},
|
|
|
|
{V(int(17)), V(int8(17))},
|
|
|
|
{V(int8(18)), V(uint(18))},
|
|
|
|
{V(uint(19)), V(int8(19))},
|
|
|
|
{V(int8(20)), V(uintptr(20))},
|
|
|
|
{V(uintptr(21)), V(int8(21))},
|
|
|
|
{V(int8(22)), V(float32(22))},
|
|
|
|
{V(float32(23)), V(int8(23))},
|
|
|
|
{V(int8(24)), V(float64(24))},
|
|
|
|
{V(float64(25)), V(int8(25))},
|
|
|
|
{V(uint8(26)), V(uint8(26))},
|
|
|
|
{V(uint8(27)), V(int16(27))},
|
|
|
|
{V(int16(28)), V(uint8(28))},
|
|
|
|
{V(uint8(29)), V(uint16(29))},
|
|
|
|
{V(uint16(30)), V(uint8(30))},
|
|
|
|
{V(uint8(31)), V(int32(31))},
|
|
|
|
{V(int32(32)), V(uint8(32))},
|
|
|
|
{V(uint8(33)), V(uint32(33))},
|
|
|
|
{V(uint32(34)), V(uint8(34))},
|
|
|
|
{V(uint8(35)), V(int64(35))},
|
|
|
|
{V(int64(36)), V(uint8(36))},
|
|
|
|
{V(uint8(37)), V(uint64(37))},
|
|
|
|
{V(uint64(38)), V(uint8(38))},
|
|
|
|
{V(uint8(39)), V(int(39))},
|
|
|
|
{V(int(40)), V(uint8(40))},
|
|
|
|
{V(uint8(41)), V(uint(41))},
|
|
|
|
{V(uint(42)), V(uint8(42))},
|
|
|
|
{V(uint8(43)), V(uintptr(43))},
|
|
|
|
{V(uintptr(44)), V(uint8(44))},
|
|
|
|
{V(uint8(45)), V(float32(45))},
|
|
|
|
{V(float32(46)), V(uint8(46))},
|
|
|
|
{V(uint8(47)), V(float64(47))},
|
|
|
|
{V(float64(48)), V(uint8(48))},
|
|
|
|
{V(int16(49)), V(int16(49))},
|
|
|
|
{V(int16(50)), V(uint16(50))},
|
|
|
|
{V(uint16(51)), V(int16(51))},
|
|
|
|
{V(int16(52)), V(int32(52))},
|
|
|
|
{V(int32(53)), V(int16(53))},
|
|
|
|
{V(int16(54)), V(uint32(54))},
|
|
|
|
{V(uint32(55)), V(int16(55))},
|
|
|
|
{V(int16(56)), V(int64(56))},
|
|
|
|
{V(int64(57)), V(int16(57))},
|
|
|
|
{V(int16(58)), V(uint64(58))},
|
|
|
|
{V(uint64(59)), V(int16(59))},
|
|
|
|
{V(int16(60)), V(int(60))},
|
|
|
|
{V(int(61)), V(int16(61))},
|
|
|
|
{V(int16(62)), V(uint(62))},
|
|
|
|
{V(uint(63)), V(int16(63))},
|
|
|
|
{V(int16(64)), V(uintptr(64))},
|
|
|
|
{V(uintptr(65)), V(int16(65))},
|
|
|
|
{V(int16(66)), V(float32(66))},
|
|
|
|
{V(float32(67)), V(int16(67))},
|
|
|
|
{V(int16(68)), V(float64(68))},
|
|
|
|
{V(float64(69)), V(int16(69))},
|
|
|
|
{V(uint16(70)), V(uint16(70))},
|
|
|
|
{V(uint16(71)), V(int32(71))},
|
|
|
|
{V(int32(72)), V(uint16(72))},
|
|
|
|
{V(uint16(73)), V(uint32(73))},
|
|
|
|
{V(uint32(74)), V(uint16(74))},
|
|
|
|
{V(uint16(75)), V(int64(75))},
|
|
|
|
{V(int64(76)), V(uint16(76))},
|
|
|
|
{V(uint16(77)), V(uint64(77))},
|
|
|
|
{V(uint64(78)), V(uint16(78))},
|
|
|
|
{V(uint16(79)), V(int(79))},
|
|
|
|
{V(int(80)), V(uint16(80))},
|
|
|
|
{V(uint16(81)), V(uint(81))},
|
|
|
|
{V(uint(82)), V(uint16(82))},
|
|
|
|
{V(uint16(83)), V(uintptr(83))},
|
|
|
|
{V(uintptr(84)), V(uint16(84))},
|
|
|
|
{V(uint16(85)), V(float32(85))},
|
|
|
|
{V(float32(86)), V(uint16(86))},
|
|
|
|
{V(uint16(87)), V(float64(87))},
|
|
|
|
{V(float64(88)), V(uint16(88))},
|
|
|
|
{V(int32(89)), V(int32(89))},
|
|
|
|
{V(int32(90)), V(uint32(90))},
|
|
|
|
{V(uint32(91)), V(int32(91))},
|
|
|
|
{V(int32(92)), V(int64(92))},
|
|
|
|
{V(int64(93)), V(int32(93))},
|
|
|
|
{V(int32(94)), V(uint64(94))},
|
|
|
|
{V(uint64(95)), V(int32(95))},
|
|
|
|
{V(int32(96)), V(int(96))},
|
|
|
|
{V(int(97)), V(int32(97))},
|
|
|
|
{V(int32(98)), V(uint(98))},
|
|
|
|
{V(uint(99)), V(int32(99))},
|
|
|
|
{V(int32(100)), V(uintptr(100))},
|
|
|
|
{V(uintptr(101)), V(int32(101))},
|
|
|
|
{V(int32(102)), V(float32(102))},
|
|
|
|
{V(float32(103)), V(int32(103))},
|
|
|
|
{V(int32(104)), V(float64(104))},
|
|
|
|
{V(float64(105)), V(int32(105))},
|
|
|
|
{V(uint32(106)), V(uint32(106))},
|
|
|
|
{V(uint32(107)), V(int64(107))},
|
|
|
|
{V(int64(108)), V(uint32(108))},
|
|
|
|
{V(uint32(109)), V(uint64(109))},
|
|
|
|
{V(uint64(110)), V(uint32(110))},
|
|
|
|
{V(uint32(111)), V(int(111))},
|
|
|
|
{V(int(112)), V(uint32(112))},
|
|
|
|
{V(uint32(113)), V(uint(113))},
|
|
|
|
{V(uint(114)), V(uint32(114))},
|
|
|
|
{V(uint32(115)), V(uintptr(115))},
|
|
|
|
{V(uintptr(116)), V(uint32(116))},
|
|
|
|
{V(uint32(117)), V(float32(117))},
|
|
|
|
{V(float32(118)), V(uint32(118))},
|
|
|
|
{V(uint32(119)), V(float64(119))},
|
|
|
|
{V(float64(120)), V(uint32(120))},
|
|
|
|
{V(int64(121)), V(int64(121))},
|
|
|
|
{V(int64(122)), V(uint64(122))},
|
|
|
|
{V(uint64(123)), V(int64(123))},
|
|
|
|
{V(int64(124)), V(int(124))},
|
|
|
|
{V(int(125)), V(int64(125))},
|
|
|
|
{V(int64(126)), V(uint(126))},
|
|
|
|
{V(uint(127)), V(int64(127))},
|
|
|
|
{V(int64(128)), V(uintptr(128))},
|
|
|
|
{V(uintptr(129)), V(int64(129))},
|
|
|
|
{V(int64(130)), V(float32(130))},
|
|
|
|
{V(float32(131)), V(int64(131))},
|
|
|
|
{V(int64(132)), V(float64(132))},
|
|
|
|
{V(float64(133)), V(int64(133))},
|
|
|
|
{V(uint64(134)), V(uint64(134))},
|
|
|
|
{V(uint64(135)), V(int(135))},
|
|
|
|
{V(int(136)), V(uint64(136))},
|
|
|
|
{V(uint64(137)), V(uint(137))},
|
|
|
|
{V(uint(138)), V(uint64(138))},
|
|
|
|
{V(uint64(139)), V(uintptr(139))},
|
|
|
|
{V(uintptr(140)), V(uint64(140))},
|
|
|
|
{V(uint64(141)), V(float32(141))},
|
|
|
|
{V(float32(142)), V(uint64(142))},
|
|
|
|
{V(uint64(143)), V(float64(143))},
|
|
|
|
{V(float64(144)), V(uint64(144))},
|
|
|
|
{V(int(145)), V(int(145))},
|
|
|
|
{V(int(146)), V(uint(146))},
|
|
|
|
{V(uint(147)), V(int(147))},
|
|
|
|
{V(int(148)), V(uintptr(148))},
|
|
|
|
{V(uintptr(149)), V(int(149))},
|
|
|
|
{V(int(150)), V(float32(150))},
|
|
|
|
{V(float32(151)), V(int(151))},
|
|
|
|
{V(int(152)), V(float64(152))},
|
|
|
|
{V(float64(153)), V(int(153))},
|
|
|
|
{V(uint(154)), V(uint(154))},
|
|
|
|
{V(uint(155)), V(uintptr(155))},
|
|
|
|
{V(uintptr(156)), V(uint(156))},
|
|
|
|
{V(uint(157)), V(float32(157))},
|
|
|
|
{V(float32(158)), V(uint(158))},
|
|
|
|
{V(uint(159)), V(float64(159))},
|
|
|
|
{V(float64(160)), V(uint(160))},
|
|
|
|
{V(uintptr(161)), V(uintptr(161))},
|
|
|
|
{V(uintptr(162)), V(float32(162))},
|
|
|
|
{V(float32(163)), V(uintptr(163))},
|
|
|
|
{V(uintptr(164)), V(float64(164))},
|
|
|
|
{V(float64(165)), V(uintptr(165))},
|
|
|
|
{V(float32(166)), V(float32(166))},
|
|
|
|
{V(float32(167)), V(float64(167))},
|
|
|
|
{V(float64(168)), V(float32(168))},
|
|
|
|
{V(float64(169)), V(float64(169))},
|
|
|
|
|
|
|
|
// truncation
|
|
|
|
{V(float64(1.5)), V(int(1))},
|
|
|
|
|
|
|
|
// complex
|
|
|
|
{V(complex64(1i)), V(complex64(1i))},
|
|
|
|
{V(complex64(2i)), V(complex128(2i))},
|
|
|
|
{V(complex128(3i)), V(complex64(3i))},
|
|
|
|
{V(complex128(4i)), V(complex128(4i))},
|
|
|
|
|
|
|
|
// string
|
|
|
|
{V(string("hello")), V(string("hello"))},
|
|
|
|
{V(string("bytes1")), V([]byte("bytes1"))},
|
|
|
|
{V([]byte("bytes2")), V(string("bytes2"))},
|
|
|
|
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
|
|
|
{V(string("runes♝")), V([]rune("runes♝"))},
|
|
|
|
{V([]rune("runes♕")), V(string("runes♕"))},
|
|
|
|
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
|
|
|
{V(int('a')), V(string("a"))},
|
|
|
|
{V(int8('a')), V(string("a"))},
|
|
|
|
{V(int16('a')), V(string("a"))},
|
|
|
|
{V(int32('a')), V(string("a"))},
|
|
|
|
{V(int64('a')), V(string("a"))},
|
|
|
|
{V(uint('a')), V(string("a"))},
|
|
|
|
{V(uint8('a')), V(string("a"))},
|
|
|
|
{V(uint16('a')), V(string("a"))},
|
|
|
|
{V(uint32('a')), V(string("a"))},
|
|
|
|
{V(uint64('a')), V(string("a"))},
|
|
|
|
{V(uintptr('a')), V(string("a"))},
|
|
|
|
{V(int(-1)), V(string("\uFFFD"))},
|
|
|
|
{V(int8(-2)), V(string("\uFFFD"))},
|
|
|
|
{V(int16(-3)), V(string("\uFFFD"))},
|
|
|
|
{V(int32(-4)), V(string("\uFFFD"))},
|
|
|
|
{V(int64(-5)), V(string("\uFFFD"))},
|
|
|
|
{V(uint(0x110001)), V(string("\uFFFD"))},
|
|
|
|
{V(uint32(0x110002)), V(string("\uFFFD"))},
|
|
|
|
{V(uint64(0x110003)), V(string("\uFFFD"))},
|
|
|
|
{V(uintptr(0x110004)), V(string("\uFFFD"))},
|
|
|
|
|
|
|
|
// named string
|
|
|
|
{V(MyString("hello")), V(string("hello"))},
|
|
|
|
{V(string("hello")), V(MyString("hello"))},
|
|
|
|
{V(string("hello")), V(string("hello"))},
|
|
|
|
{V(MyString("hello")), V(MyString("hello"))},
|
|
|
|
{V(MyString("bytes1")), V([]byte("bytes1"))},
|
|
|
|
{V([]byte("bytes2")), V(MyString("bytes2"))},
|
|
|
|
{V([]byte("bytes3")), V([]byte("bytes3"))},
|
|
|
|
{V(MyString("runes♝")), V([]rune("runes♝"))},
|
|
|
|
{V([]rune("runes♕")), V(MyString("runes♕"))},
|
|
|
|
{V([]rune("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
|
|
|
{V([]rune("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
|
|
|
{V(MyRunes("runes🙈🙉🙊")), V([]rune("runes🙈🙉🙊"))},
|
|
|
|
{V(int('a')), V(MyString("a"))},
|
|
|
|
{V(int8('a')), V(MyString("a"))},
|
|
|
|
{V(int16('a')), V(MyString("a"))},
|
|
|
|
{V(int32('a')), V(MyString("a"))},
|
|
|
|
{V(int64('a')), V(MyString("a"))},
|
|
|
|
{V(uint('a')), V(MyString("a"))},
|
|
|
|
{V(uint8('a')), V(MyString("a"))},
|
|
|
|
{V(uint16('a')), V(MyString("a"))},
|
|
|
|
{V(uint32('a')), V(MyString("a"))},
|
|
|
|
{V(uint64('a')), V(MyString("a"))},
|
|
|
|
{V(uintptr('a')), V(MyString("a"))},
|
|
|
|
{V(int(-1)), V(MyString("\uFFFD"))},
|
|
|
|
{V(int8(-2)), V(MyString("\uFFFD"))},
|
|
|
|
{V(int16(-3)), V(MyString("\uFFFD"))},
|
|
|
|
{V(int32(-4)), V(MyString("\uFFFD"))},
|
|
|
|
{V(int64(-5)), V(MyString("\uFFFD"))},
|
|
|
|
{V(uint(0x110001)), V(MyString("\uFFFD"))},
|
|
|
|
{V(uint32(0x110002)), V(MyString("\uFFFD"))},
|
|
|
|
{V(uint64(0x110003)), V(MyString("\uFFFD"))},
|
|
|
|
{V(uintptr(0x110004)), V(MyString("\uFFFD"))},
|
|
|
|
|
|
|
|
// named []byte
|
|
|
|
{V(string("bytes1")), V(MyBytes("bytes1"))},
|
|
|
|
{V(MyBytes("bytes2")), V(string("bytes2"))},
|
|
|
|
{V(MyBytes("bytes3")), V(MyBytes("bytes3"))},
|
|
|
|
{V(MyString("bytes1")), V(MyBytes("bytes1"))},
|
|
|
|
{V(MyBytes("bytes2")), V(MyString("bytes2"))},
|
|
|
|
|
|
|
|
// named []rune
|
|
|
|
{V(string("runes♝")), V(MyRunes("runes♝"))},
|
|
|
|
{V(MyRunes("runes♕")), V(string("runes♕"))},
|
|
|
|
{V(MyRunes("runes🙈🙉🙊")), V(MyRunes("runes🙈🙉🙊"))},
|
|
|
|
{V(MyString("runes♝")), V(MyRunes("runes♝"))},
|
|
|
|
{V(MyRunes("runes♕")), V(MyString("runes♕"))},
|
|
|
|
|
|
|
|
// named types and equal underlying types
|
|
|
|
{V(new(int)), V(new(integer))},
|
|
|
|
{V(new(integer)), V(new(int))},
|
|
|
|
{V(Empty{}), V(struct{}{})},
|
|
|
|
{V(new(Empty)), V(new(struct{}))},
|
|
|
|
{V(struct{}{}), V(Empty{})},
|
|
|
|
{V(new(struct{})), V(new(Empty))},
|
|
|
|
{V(Empty{}), V(Empty{})},
|
|
|
|
{V(MyBytes{}), V([]byte{})},
|
|
|
|
{V([]byte{}), V(MyBytes{})},
|
|
|
|
{V((func())(nil)), V(MyFunc(nil))},
|
|
|
|
{V((MyFunc)(nil)), V((func())(nil))},
|
|
|
|
|
|
|
|
// can convert *byte and *MyByte
|
|
|
|
{V((*byte)(nil)), V((*MyByte)(nil))},
|
|
|
|
{V((*MyByte)(nil)), V((*byte)(nil))},
|
|
|
|
|
|
|
|
// cannot convert mismatched array sizes
|
|
|
|
{V([2]byte{}), V([2]byte{})},
|
|
|
|
{V([3]byte{}), V([3]byte{})},
|
|
|
|
|
|
|
|
// cannot convert other instances
|
|
|
|
{V((**byte)(nil)), V((**byte)(nil))},
|
|
|
|
{V((**MyByte)(nil)), V((**MyByte)(nil))},
|
|
|
|
{V((chan byte)(nil)), V((chan byte)(nil))},
|
|
|
|
{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
|
|
|
|
{V(([]byte)(nil)), V(([]byte)(nil))},
|
|
|
|
{V(([]MyByte)(nil)), V(([]MyByte)(nil))},
|
|
|
|
{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
|
|
|
|
{V((map[int]MyByte)(nil)), V((map[int]MyByte)(nil))},
|
|
|
|
{V((map[byte]int)(nil)), V((map[byte]int)(nil))},
|
|
|
|
{V((map[MyByte]int)(nil)), V((map[MyByte]int)(nil))},
|
|
|
|
{V([2]byte{}), V([2]byte{})},
|
|
|
|
{V([2]MyByte{}), V([2]MyByte{})},
|
|
|
|
|
|
|
|
// other
|
|
|
|
{V((***int)(nil)), V((***int)(nil))},
|
|
|
|
{V((***byte)(nil)), V((***byte)(nil))},
|
|
|
|
{V((***int32)(nil)), V((***int32)(nil))},
|
|
|
|
{V((***int64)(nil)), V((***int64)(nil))},
|
|
|
|
{V((chan int)(nil)), V((<-chan int)(nil))},
|
|
|
|
{V((chan int)(nil)), V((chan<- int)(nil))},
|
|
|
|
{V((chan string)(nil)), V((<-chan string)(nil))},
|
|
|
|
{V((chan string)(nil)), V((chan<- string)(nil))},
|
|
|
|
{V((chan byte)(nil)), V((chan byte)(nil))},
|
|
|
|
{V((chan MyByte)(nil)), V((chan MyByte)(nil))},
|
|
|
|
{V((map[int]bool)(nil)), V((map[int]bool)(nil))},
|
|
|
|
{V((map[int]byte)(nil)), V((map[int]byte)(nil))},
|
|
|
|
{V((map[uint]bool)(nil)), V((map[uint]bool)(nil))},
|
|
|
|
{V([]uint(nil)), V([]uint(nil))},
|
|
|
|
{V([]int(nil)), V([]int(nil))},
|
|
|
|
{V(new(interface{})), V(new(interface{}))},
|
|
|
|
{V(new(io.Reader)), V(new(io.Reader))},
|
|
|
|
{V(new(io.Writer)), V(new(io.Writer))},
|
|
|
|
|
|
|
|
// interfaces
|
|
|
|
{V(int(1)), EmptyInterfaceV(int(1))},
|
|
|
|
{V(string("hello")), EmptyInterfaceV(string("hello"))},
|
|
|
|
{V(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
|
|
|
|
{ReadWriterV(new(bytes.Buffer)), ReaderV(new(bytes.Buffer))},
|
|
|
|
{V(new(bytes.Buffer)), ReadWriterV(new(bytes.Buffer))},
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestConvert(t *testing.T) {
|
|
|
|
canConvert := map[[2]Type]bool{}
|
|
|
|
all := map[Type]bool{}
|
|
|
|
|
|
|
|
for _, tt := range convertTests {
|
|
|
|
t1 := tt.in.Type()
|
|
|
|
if !t1.ConvertibleTo(t1) {
|
|
|
|
t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t1)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
t2 := tt.out.Type()
|
|
|
|
if !t1.ConvertibleTo(t2) {
|
|
|
|
t.Errorf("(%s).ConvertibleTo(%s) = false, want true", t1, t2)
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
all[t1] = true
|
|
|
|
all[t2] = true
|
|
|
|
canConvert[[2]Type{t1, t2}] = true
|
|
|
|
|
2013-08-20 22:41:55 -06:00
|
|
|
// vout1 represents the in value converted to the in type.
|
2012-09-22 06:52:27 -06:00
|
|
|
v1 := tt.in
|
|
|
|
vout1 := v1.Convert(t1)
|
|
|
|
out1 := vout1.Interface()
|
|
|
|
if vout1.Type() != tt.in.Type() || !DeepEqual(out1, tt.in.Interface()) {
|
2013-08-20 22:41:55 -06:00
|
|
|
t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t1, out1, tt.in.Interface())
|
2012-09-22 06:52:27 -06:00
|
|
|
}
|
|
|
|
|
2013-08-20 22:41:55 -06:00
|
|
|
// vout2 represents the in value converted to the out type.
|
|
|
|
vout2 := v1.Convert(t2)
|
|
|
|
out2 := vout2.Interface()
|
|
|
|
if vout2.Type() != tt.out.Type() || !DeepEqual(out2, tt.out.Interface()) {
|
|
|
|
t.Errorf("ValueOf(%T(%[1]v)).Convert(%s) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out2, tt.out.Interface())
|
|
|
|
}
|
|
|
|
|
|
|
|
// vout3 represents a new value of the out type, set to vout2. This makes
|
|
|
|
// sure the converted value vout2 is really usable as a regular value.
|
|
|
|
vout3 := New(t2).Elem()
|
|
|
|
vout3.Set(vout2)
|
|
|
|
out3 := vout3.Interface()
|
|
|
|
if vout3.Type() != tt.out.Type() || !DeepEqual(out3, tt.out.Interface()) {
|
|
|
|
t.Errorf("Set(ValueOf(%T(%[1]v)).Convert(%s)) = %T(%[3]v), want %T(%[4]v)", tt.in.Interface(), t2, out3, tt.out.Interface())
|
2012-09-22 06:52:27 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
if IsRO(v1) {
|
|
|
|
t.Errorf("table entry %v is RO, should not be", v1)
|
|
|
|
}
|
|
|
|
if IsRO(vout1) {
|
|
|
|
t.Errorf("self-conversion output %v is RO, should not be", vout1)
|
|
|
|
}
|
2013-08-20 22:41:55 -06:00
|
|
|
if IsRO(vout2) {
|
|
|
|
t.Errorf("conversion output %v is RO, should not be", vout2)
|
|
|
|
}
|
|
|
|
if IsRO(vout3) {
|
|
|
|
t.Errorf("set(conversion output) %v is RO, should not be", vout3)
|
2012-09-22 06:52:27 -06:00
|
|
|
}
|
|
|
|
if !IsRO(MakeRO(v1).Convert(t1)) {
|
|
|
|
t.Errorf("RO self-conversion output %v is not RO, should be", v1)
|
|
|
|
}
|
|
|
|
if !IsRO(MakeRO(v1).Convert(t2)) {
|
|
|
|
t.Errorf("RO conversion output %v is not RO, should be", v1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Assume that of all the types we saw during the tests,
|
|
|
|
// if there wasn't an explicit entry for a conversion between
|
|
|
|
// a pair of types, then it's not to be allowed. This checks for
|
|
|
|
// things like 'int64' converting to '*int'.
|
|
|
|
for t1 := range all {
|
|
|
|
for t2 := range all {
|
|
|
|
expectOK := t1 == t2 || canConvert[[2]Type{t1, t2}] || t2.Kind() == Interface && t2.NumMethod() == 0
|
|
|
|
if ok := t1.ConvertibleTo(t2); ok != expectOK {
|
|
|
|
t.Errorf("(%s).ConvertibleTo(%s) = %v, want %v", t1, t2, ok, expectOK)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-10-26 00:39:36 -06:00
|
|
|
func TestOverflow(t *testing.T) {
|
|
|
|
if ovf := V(float64(0)).OverflowFloat(1e300); ovf {
|
|
|
|
t.Errorf("%v wrongly overflows float64", 1e300)
|
|
|
|
}
|
|
|
|
|
|
|
|
maxFloat32 := float64((1<<24 - 1) << (127 - 23))
|
|
|
|
if ovf := V(float32(0)).OverflowFloat(maxFloat32); ovf {
|
|
|
|
t.Errorf("%v wrongly overflows float32", maxFloat32)
|
|
|
|
}
|
|
|
|
ovfFloat32 := float64((1<<24-1)<<(127-23) + 1<<(127-52))
|
|
|
|
if ovf := V(float32(0)).OverflowFloat(ovfFloat32); !ovf {
|
|
|
|
t.Errorf("%v should overflow float32", ovfFloat32)
|
|
|
|
}
|
|
|
|
if ovf := V(float32(0)).OverflowFloat(-ovfFloat32); !ovf {
|
|
|
|
t.Errorf("%v should overflow float32", -ovfFloat32)
|
|
|
|
}
|
|
|
|
|
|
|
|
maxInt32 := int64(0x7fffffff)
|
|
|
|
if ovf := V(int32(0)).OverflowInt(maxInt32); ovf {
|
|
|
|
t.Errorf("%v wrongly overflows int32", maxInt32)
|
|
|
|
}
|
|
|
|
if ovf := V(int32(0)).OverflowInt(-1 << 31); ovf {
|
|
|
|
t.Errorf("%v wrongly overflows int32", -int64(1)<<31)
|
|
|
|
}
|
|
|
|
ovfInt32 := int64(1 << 31)
|
|
|
|
if ovf := V(int32(0)).OverflowInt(ovfInt32); !ovf {
|
|
|
|
t.Errorf("%v should overflow int32", ovfInt32)
|
|
|
|
}
|
|
|
|
|
|
|
|
maxUint32 := uint64(0xffffffff)
|
|
|
|
if ovf := V(uint32(0)).OverflowUint(maxUint32); ovf {
|
|
|
|
t.Errorf("%v wrongly overflows uint32", maxUint32)
|
|
|
|
}
|
|
|
|
ovfUint32 := uint64(1 << 32)
|
|
|
|
if ovf := V(uint32(0)).OverflowUint(ovfUint32); !ovf {
|
|
|
|
t.Errorf("%v should overflow uint32", ovfUint32)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
func checkSameType(t *testing.T, x, y interface{}) {
|
|
|
|
if TypeOf(x) != TypeOf(y) {
|
|
|
|
t.Errorf("did not find preexisting type for %s (vs %s)", TypeOf(x), TypeOf(y))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestArrayOf(t *testing.T) {
|
|
|
|
// check construction and use of type not in binary
|
|
|
|
type T int
|
|
|
|
at := ArrayOf(10, TypeOf(T(1)))
|
|
|
|
v := New(at).Elem()
|
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
v.Index(i).Set(ValueOf(T(i)))
|
|
|
|
}
|
|
|
|
s := fmt.Sprint(v.Interface())
|
|
|
|
want := "[0 1 2 3 4 5 6 7 8 9]"
|
|
|
|
if s != want {
|
|
|
|
t.Errorf("constructed array = %s, want %s", s, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that type already in binary is found
|
|
|
|
checkSameType(t, Zero(ArrayOf(5, TypeOf(T(1)))).Interface(), [5]T{})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSliceOf(t *testing.T) {
|
|
|
|
// check construction and use of type not in binary
|
|
|
|
type T int
|
|
|
|
st := SliceOf(TypeOf(T(1)))
|
|
|
|
v := MakeSlice(st, 10, 10)
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
for i := 0; i < v.Len(); i++ {
|
|
|
|
v.Index(i).Set(ValueOf(T(i)))
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
}
|
|
|
|
s := fmt.Sprint(v.Interface())
|
|
|
|
want := "[0 1 2 3 4 5 6 7 8 9]"
|
|
|
|
if s != want {
|
|
|
|
t.Errorf("constructed slice = %s, want %s", s, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that type already in binary is found
|
|
|
|
type T1 int
|
|
|
|
checkSameType(t, Zero(SliceOf(TypeOf(T1(1)))).Interface(), []T1{})
|
|
|
|
}
|
|
|
|
|
2013-05-27 01:29:11 -06:00
|
|
|
func TestSliceOverflow(t *testing.T) {
|
|
|
|
// check that MakeSlice panics when size of slice overflows uint
|
|
|
|
const S = 1e6
|
|
|
|
s := uint(S)
|
|
|
|
l := (1<<(unsafe.Sizeof((*byte)(nil))*8)-1)/s + 1
|
|
|
|
if l*s >= s {
|
|
|
|
t.Fatal("slice size does not overflow")
|
|
|
|
}
|
|
|
|
var x [S]byte
|
|
|
|
st := SliceOf(TypeOf(x))
|
|
|
|
defer func() {
|
|
|
|
err := recover()
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("slice overflow does not panic")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
MakeSlice(st, int(l), int(l))
|
|
|
|
}
|
|
|
|
|
2013-03-26 12:50:29 -06:00
|
|
|
func TestSliceOfGC(t *testing.T) {
|
|
|
|
type T *uintptr
|
|
|
|
tt := TypeOf(T(nil))
|
|
|
|
st := SliceOf(tt)
|
|
|
|
const n = 100
|
|
|
|
var x []interface{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v := MakeSlice(st, n, n)
|
|
|
|
for j := 0; j < v.Len(); j++ {
|
|
|
|
p := new(uintptr)
|
|
|
|
*p = uintptr(i*n + j)
|
|
|
|
v.Index(j).Set(ValueOf(p).Convert(tt))
|
|
|
|
}
|
|
|
|
x = append(x, v.Interface())
|
|
|
|
}
|
|
|
|
runtime.GC()
|
|
|
|
|
|
|
|
for i, xi := range x {
|
|
|
|
v := ValueOf(xi)
|
|
|
|
for j := 0; j < v.Len(); j++ {
|
|
|
|
k := v.Index(j).Elem().Interface()
|
|
|
|
if k != uintptr(i*n+j) {
|
|
|
|
t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
func TestChanOf(t *testing.T) {
|
|
|
|
// check construction and use of type not in binary
|
|
|
|
type T string
|
|
|
|
ct := ChanOf(BothDir, TypeOf(T("")))
|
|
|
|
v := MakeChan(ct, 2)
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
v.Send(ValueOf(T("hello")))
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
v.Send(ValueOf(T("world")))
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
|
|
|
|
sv1, _ := v.Recv()
|
|
|
|
sv2, _ := v.Recv()
|
|
|
|
s1 := sv1.String()
|
|
|
|
s2 := sv2.String()
|
|
|
|
if s1 != "hello" || s2 != "world" {
|
|
|
|
t.Errorf("constructed chan: have %q, %q, want %q, %q", s1, s2, "hello", "world")
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that type already in binary is found
|
|
|
|
type T1 int
|
|
|
|
checkSameType(t, Zero(ChanOf(BothDir, TypeOf(T1(1)))).Interface(), (chan T1)(nil))
|
|
|
|
}
|
|
|
|
|
2013-03-26 12:50:29 -06:00
|
|
|
func TestChanOfGC(t *testing.T) {
|
|
|
|
done := make(chan bool, 1)
|
|
|
|
go func() {
|
|
|
|
select {
|
|
|
|
case <-done:
|
|
|
|
case <-time.After(5 * time.Second):
|
|
|
|
panic("deadlock in TestChanOfGC")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
|
|
|
|
defer func() {
|
|
|
|
done <- true
|
|
|
|
}()
|
|
|
|
|
|
|
|
type T *uintptr
|
|
|
|
tt := TypeOf(T(nil))
|
|
|
|
ct := ChanOf(BothDir, tt)
|
|
|
|
|
|
|
|
// NOTE: The garbage collector handles allocated channels specially,
|
|
|
|
// so we have to save pointers to channels in x; the pointer code will
|
|
|
|
// use the gc info in the newly constructed chan type.
|
|
|
|
const n = 100
|
|
|
|
var x []interface{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v := MakeChan(ct, n)
|
|
|
|
for j := 0; j < n; j++ {
|
|
|
|
p := new(uintptr)
|
|
|
|
*p = uintptr(i*n + j)
|
|
|
|
v.Send(ValueOf(p).Convert(tt))
|
|
|
|
}
|
|
|
|
pv := New(ct)
|
|
|
|
pv.Elem().Set(v)
|
|
|
|
x = append(x, pv.Interface())
|
|
|
|
}
|
|
|
|
runtime.GC()
|
|
|
|
|
|
|
|
for i, xi := range x {
|
|
|
|
v := ValueOf(xi).Elem()
|
|
|
|
for j := 0; j < n; j++ {
|
|
|
|
pv, _ := v.Recv()
|
|
|
|
k := pv.Elem().Interface()
|
|
|
|
if k != uintptr(i*n+j) {
|
|
|
|
t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
func TestMapOf(t *testing.T) {
|
|
|
|
// check construction and use of type not in binary
|
|
|
|
type K string
|
|
|
|
type V float64
|
|
|
|
|
|
|
|
v := MakeMap(MapOf(TypeOf(K("")), TypeOf(V(0))))
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
v.SetMapIndex(ValueOf(K("a")), ValueOf(V(1)))
|
2013-03-26 12:50:29 -06:00
|
|
|
runtime.GC()
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
|
|
|
|
s := fmt.Sprint(v.Interface())
|
|
|
|
want := "map[a:1]"
|
|
|
|
if s != want {
|
|
|
|
t.Errorf("constructed map = %s, want %s", s, want)
|
|
|
|
}
|
|
|
|
|
|
|
|
// check that type already in binary is found
|
|
|
|
checkSameType(t, Zero(MapOf(TypeOf(V(0)), TypeOf(K("")))).Interface(), map[V]K(nil))
|
2013-03-26 12:50:29 -06:00
|
|
|
|
|
|
|
// check that invalid key type panics
|
|
|
|
shouldPanic(func() { MapOf(TypeOf((func())(nil)), TypeOf(false)) })
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMapOfGCKeys(t *testing.T) {
|
|
|
|
type T *uintptr
|
|
|
|
tt := TypeOf(T(nil))
|
|
|
|
mt := MapOf(tt, TypeOf(false))
|
|
|
|
|
|
|
|
// NOTE: The garbage collector handles allocated maps specially,
|
|
|
|
// so we have to save pointers to maps in x; the pointer code will
|
|
|
|
// use the gc info in the newly constructed map type.
|
|
|
|
const n = 100
|
|
|
|
var x []interface{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v := MakeMap(mt)
|
|
|
|
for j := 0; j < n; j++ {
|
|
|
|
p := new(uintptr)
|
|
|
|
*p = uintptr(i*n + j)
|
|
|
|
v.SetMapIndex(ValueOf(p).Convert(tt), ValueOf(true))
|
|
|
|
}
|
|
|
|
pv := New(mt)
|
|
|
|
pv.Elem().Set(v)
|
|
|
|
x = append(x, pv.Interface())
|
|
|
|
}
|
|
|
|
runtime.GC()
|
|
|
|
|
|
|
|
for i, xi := range x {
|
|
|
|
v := ValueOf(xi).Elem()
|
|
|
|
var out []int
|
|
|
|
for _, kv := range v.MapKeys() {
|
|
|
|
out = append(out, int(kv.Elem().Interface().(uintptr)))
|
|
|
|
}
|
|
|
|
sort.Ints(out)
|
|
|
|
for j, k := range out {
|
|
|
|
if k != i*n+j {
|
|
|
|
t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestMapOfGCValues(t *testing.T) {
|
|
|
|
type T *uintptr
|
|
|
|
tt := TypeOf(T(nil))
|
|
|
|
mt := MapOf(TypeOf(1), tt)
|
|
|
|
|
|
|
|
// NOTE: The garbage collector handles allocated maps specially,
|
|
|
|
// so we have to save pointers to maps in x; the pointer code will
|
|
|
|
// use the gc info in the newly constructed map type.
|
|
|
|
const n = 100
|
|
|
|
var x []interface{}
|
|
|
|
for i := 0; i < n; i++ {
|
|
|
|
v := MakeMap(mt)
|
|
|
|
for j := 0; j < n; j++ {
|
|
|
|
p := new(uintptr)
|
|
|
|
*p = uintptr(i*n + j)
|
|
|
|
v.SetMapIndex(ValueOf(j), ValueOf(p).Convert(tt))
|
|
|
|
}
|
|
|
|
pv := New(mt)
|
|
|
|
pv.Elem().Set(v)
|
|
|
|
x = append(x, pv.Interface())
|
|
|
|
}
|
|
|
|
runtime.GC()
|
|
|
|
|
|
|
|
for i, xi := range x {
|
|
|
|
v := ValueOf(xi).Elem()
|
|
|
|
for j := 0; j < n; j++ {
|
|
|
|
k := v.MapIndex(ValueOf(j)).Elem().Interface().(uintptr)
|
|
|
|
if k != uintptr(i*n+j) {
|
|
|
|
t.Errorf("lost x[%d][%d] = %d, want %d", i, j, k, i*n+j)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
reflect: add ArrayOf, ChanOf, MapOf, SliceOf
In order to add these, we need to be able to find references
to such types that already exist in the binary. To do that, introduce
a new linker section holding a list of the types corresponding to
arrays, chans, maps, and slices.
To offset the storage cost of this list, and to simplify the code,
remove the interface{} header from the representation of a
runtime type. It was used in early versions of the code but was
made obsolete by the kind field: a switch on kind is more efficient
than a type switch.
In the godoc binary, removing the interface{} header cuts two
words from each of about 10,000 types. Adding back the list of pointers
to array, chan, map, and slice types reintroduces one word for
each of about 500 types. On a 64-bit machine, then, this CL *removes*
a net 156 kB of read-only data from the binary.
This CL does not include the needed support for precise garbage
collection. I have created issue 4375 to track that.
This CL also does not set the 'algorithm' - specifically the equality
and copy functions - for a new array correctly, so I have unexported
ArrayOf for now. That is also part of issue 4375.
Fixes #2339.
R=r, remyoudompheng, mirtchovski, iant
CC=golang-dev
https://golang.org/cl/6572043
2012-11-13 11:06:29 -07:00
|
|
|
}
|
|
|
|
|
2012-09-05 07:35:53 -06:00
|
|
|
type B1 struct {
|
|
|
|
X int
|
|
|
|
Y int
|
|
|
|
Z int
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkFieldByName1(b *testing.B) {
|
|
|
|
t := TypeOf(B1{})
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
t.FieldByName("Z")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkFieldByName2(b *testing.B) {
|
|
|
|
t := TypeOf(S3{})
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
t.FieldByName("B")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type R0 struct {
|
|
|
|
*R1
|
|
|
|
*R2
|
|
|
|
*R3
|
|
|
|
*R4
|
|
|
|
}
|
|
|
|
|
|
|
|
type R1 struct {
|
|
|
|
*R5
|
|
|
|
*R6
|
|
|
|
*R7
|
|
|
|
*R8
|
|
|
|
}
|
|
|
|
|
|
|
|
type R2 R1
|
|
|
|
type R3 R1
|
|
|
|
type R4 R1
|
|
|
|
|
|
|
|
type R5 struct {
|
|
|
|
*R9
|
|
|
|
*R10
|
|
|
|
*R11
|
|
|
|
*R12
|
|
|
|
}
|
|
|
|
|
|
|
|
type R6 R5
|
|
|
|
type R7 R5
|
|
|
|
type R8 R5
|
|
|
|
|
|
|
|
type R9 struct {
|
|
|
|
*R13
|
|
|
|
*R14
|
|
|
|
*R15
|
|
|
|
*R16
|
|
|
|
}
|
|
|
|
|
|
|
|
type R10 R9
|
|
|
|
type R11 R9
|
|
|
|
type R12 R9
|
|
|
|
|
|
|
|
type R13 struct {
|
|
|
|
*R17
|
|
|
|
*R18
|
|
|
|
*R19
|
|
|
|
*R20
|
|
|
|
}
|
|
|
|
|
|
|
|
type R14 R13
|
|
|
|
type R15 R13
|
|
|
|
type R16 R13
|
|
|
|
|
|
|
|
type R17 struct {
|
|
|
|
*R21
|
|
|
|
*R22
|
|
|
|
*R23
|
|
|
|
*R24
|
|
|
|
}
|
|
|
|
|
|
|
|
type R18 R17
|
|
|
|
type R19 R17
|
|
|
|
type R20 R17
|
|
|
|
|
|
|
|
type R21 struct {
|
|
|
|
X int
|
|
|
|
}
|
|
|
|
|
|
|
|
type R22 R21
|
|
|
|
type R23 R21
|
|
|
|
type R24 R21
|
|
|
|
|
|
|
|
func TestEmbed(t *testing.T) {
|
|
|
|
typ := TypeOf(R0{})
|
|
|
|
f, ok := typ.FieldByName("X")
|
|
|
|
if ok {
|
|
|
|
t.Fatalf(`FieldByName("X") should fail, returned %v`, f.Index)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkFieldByName3(b *testing.B) {
|
|
|
|
t := TypeOf(R0{})
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
t.FieldByName("X")
|
|
|
|
}
|
|
|
|
}
|
2012-09-18 12:22:41 -06:00
|
|
|
|
2013-08-08 18:49:01 -06:00
|
|
|
type S struct {
|
|
|
|
i1 int64
|
|
|
|
i2 int64
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkInterfaceBig(b *testing.B) {
|
|
|
|
v := ValueOf(S{})
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
v.Interface()
|
|
|
|
}
|
|
|
|
b.StopTimer()
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAllocsInterfaceBig(t *testing.T) {
|
2013-08-20 22:00:45 -06:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping malloc count in short mode")
|
|
|
|
}
|
2013-08-08 18:49:01 -06:00
|
|
|
v := ValueOf(S{})
|
|
|
|
if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
|
2013-09-23 11:19:08 -06:00
|
|
|
t.Error("allocs:", allocs)
|
2013-08-08 18:49:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func BenchmarkInterfaceSmall(b *testing.B) {
|
|
|
|
v := ValueOf(int64(0))
|
|
|
|
for i := 0; i < b.N; i++ {
|
|
|
|
v.Interface()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAllocsInterfaceSmall(t *testing.T) {
|
2013-08-20 22:00:45 -06:00
|
|
|
if testing.Short() {
|
|
|
|
t.Skip("skipping malloc count in short mode")
|
|
|
|
}
|
2013-08-08 18:49:01 -06:00
|
|
|
v := ValueOf(int64(0))
|
|
|
|
if allocs := testing.AllocsPerRun(100, func() { v.Interface() }); allocs > 0 {
|
2013-09-23 11:19:08 -06:00
|
|
|
t.Error("allocs:", allocs)
|
2013-08-08 18:49:01 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-09-18 12:22:41 -06:00
|
|
|
// An exhaustive is a mechanism for writing exhaustive or stochastic tests.
|
|
|
|
// The basic usage is:
|
|
|
|
//
|
|
|
|
// for x.Next() {
|
|
|
|
// ... code using x.Maybe() or x.Choice(n) to create test cases ...
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// Each iteration of the loop returns a different set of results, until all
|
|
|
|
// possible result sets have been explored. It is okay for different code paths
|
|
|
|
// to make different method call sequences on x, but there must be no
|
|
|
|
// other source of non-determinism in the call sequences.
|
|
|
|
//
|
|
|
|
// When faced with a new decision, x chooses randomly. Future explorations
|
|
|
|
// of that path will choose successive values for the result. Thus, stopping
|
|
|
|
// the loop after a fixed number of iterations gives somewhat stochastic
|
|
|
|
// testing.
|
|
|
|
//
|
|
|
|
// Example:
|
|
|
|
//
|
|
|
|
// for x.Next() {
|
|
|
|
// v := make([]bool, x.Choose(4))
|
|
|
|
// for i := range v {
|
|
|
|
// v[i] = x.Maybe()
|
|
|
|
// }
|
|
|
|
// fmt.Println(v)
|
|
|
|
// }
|
|
|
|
//
|
|
|
|
// prints (in some order):
|
|
|
|
//
|
|
|
|
// []
|
|
|
|
// [false]
|
|
|
|
// [true]
|
|
|
|
// [false false]
|
|
|
|
// [false true]
|
|
|
|
// ...
|
|
|
|
// [true true]
|
|
|
|
// [false false false]
|
|
|
|
// ...
|
|
|
|
// [true true true]
|
|
|
|
// [false false false false]
|
|
|
|
// ...
|
|
|
|
// [true true true true]
|
|
|
|
//
|
|
|
|
type exhaustive struct {
|
|
|
|
r *rand.Rand
|
|
|
|
pos int
|
|
|
|
last []choice
|
|
|
|
}
|
|
|
|
|
|
|
|
type choice struct {
|
|
|
|
off int
|
|
|
|
n int
|
|
|
|
max int
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *exhaustive) Next() bool {
|
|
|
|
if x.r == nil {
|
|
|
|
x.r = rand.New(rand.NewSource(time.Now().UnixNano()))
|
|
|
|
}
|
|
|
|
x.pos = 0
|
|
|
|
if x.last == nil {
|
|
|
|
x.last = []choice{}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
for i := len(x.last) - 1; i >= 0; i-- {
|
|
|
|
c := &x.last[i]
|
|
|
|
if c.n+1 < c.max {
|
|
|
|
c.n++
|
|
|
|
x.last = x.last[:i+1]
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *exhaustive) Choose(max int) int {
|
|
|
|
if x.pos >= len(x.last) {
|
|
|
|
x.last = append(x.last, choice{x.r.Intn(max), 0, max})
|
|
|
|
}
|
|
|
|
c := &x.last[x.pos]
|
|
|
|
x.pos++
|
|
|
|
if c.max != max {
|
|
|
|
panic("inconsistent use of exhaustive tester")
|
|
|
|
}
|
|
|
|
return (c.n + c.off) % max
|
|
|
|
}
|
|
|
|
|
|
|
|
func (x *exhaustive) Maybe() bool {
|
|
|
|
return x.Choose(2) == 1
|
|
|
|
}
|