The change regards the representation of numeric types and values:
integers, floating-point numbers, and complex numbers. Before there
was a distinct Type for each type (int, int8 etc., uint uint8 etc.,
float float32 etc., complex complex64 etc.); now there is one integer
Type (IntType), one unsigned integer Type (UintType), one floating
point Type (FloatType), and one complex Type (ComplexType). Now, all
the signed integers are represented by one reflect Type (IntType) and
one reflect Value (IntValue); methods of IntType and IntValue provide
further details for the few applications that need to know. A similar
collapse occurred to the other numeric types.
The situation for numeric types is therefore much like the situation
for, say, slices: there is only one SliceType but it can represent
slices of many element types; similarly there is one IntType but it
can represent all of int, int8, int16, int32, and int64. The size of
the item is still available through its Size method, but there is also
a Kind method that returns, for IntType, one of reflect.Int,
reflect.Int8, reflect.Int16, reflect.Int32, or reflect.Int64 (That is
the only way to be sure you have an int as opposed to an int32 or
int64). We have discovered most clients of reflection don't need to
know the precise underlying integer type, however, which is why we
made this change.
Most of the code that uses reflect uses a type switch to discover the
type of the item. Now, there will not need to be a single case for
each kind of integer, only one. If you do need to know the precise
type, you can switch on the Kind of the integer type to learn more.
For values, the Set and Get routines operate on maximum-precision
values of that class of item. That is, IntValue.Get() returns an int64
and IntValue.Set() takes an int64. It is the caller's responsibility
to adjust and verify the values, but we've found this is a small burden.
Here is an example from the implementation of fmt.Printf.
Before:
switch f := value.(type) {
case *reflect.BoolValue:
p.fmtBool(f.Get(), verb, field)
case *reflect.IntValue:
p.fmtInt64(int64(f.Get()), verb, field)
case *reflect.Int8Value:
p.fmtInt64(int64(f.Get()), verb, field)
case *reflect.Int16Value:
p.fmtInt64(int64(f.Get()), verb, field)
case *reflect.Int32Value:
p.fmtInt64(int64(f.Get()), verb, field)
case *reflect.Int64Value:
p.fmtInt64(f.Get(), verb, field)
case *reflect.UintValue:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
case *reflect.Uint8Value:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
case *reflect.Uint16Value:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
case *reflect.Uint32Value:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
case *reflect.Uint64Value:
p.fmtUint64(f.Get(), verb, sharp, field)
case *reflect.UintptrValue:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
// ...
After:
switch f := value.(type) {
case *reflect.BoolValue:
p.fmtBool(f.Get(), verb, field)
case *reflect.IntValue:
p.fmtInt64(f.Get(), verb, field)
case *reflect.UintValue:
p.fmtUint64(uint64(f.Get()), verb, sharp, field)
// ...
More details will be available through godoc after the release, or you
may sync to tip now.
-rob
func setfloat(v reflect.Value, f float64) {
switch v := v.(type) {
case *reflect.FloatValue:
v.Set(f)
}
}
For the internals, see: http://golang.org/src/pkg/reflect/value.go#L156
Andrew