The document provides an overview of reflection in Go. It discusses the laws of reflection, interfaces, and the reflect package. The key points covered are:
- The three laws of reflection: reflection goes from interface value to reflection object, reflection object to interface value, and to modify a reflection object the value must be settable.
- Interfaces are statically checked and allow for dynamic dispatch via type assertions.
- The reflect package allows examining and modifying values and types at runtime. It provides utilities for querying types and values as well as setting fields and calling methods dynamically.
- The Value type provides methods for accessing and modifying values reflectively and the Type type provides information about Go types.
6. Types&and&interfaces:&Interfaces
// io.Reader is the interface that wraps the
// basic Read method.
type Reader interface {
Read(p []byte) (n int, err error)
}
var r io.Reader
r = os.Stdin
r = bufio.NewReader(r)
r = new(bytes.Buffer)
21. Type!and!Kind
var x uint8 = 'x'
v := reflect.ValueOf(x)
fmt.Println("type:", v.Type()) // uint8.
fmt.Println("kind is uint8: ",
v.Kind() == reflect.Uint8) // true.
x = uint8(v.Uint()) // v.Uint returns a uint64.
type MyInt int
var x MyInt = 7
v := reflect.ValueOf(x)
fmt.Println("kind is Int: ", v.Kind() == reflect.Int) // true.
22. 2.#Reflec(on#goes#from#reflec(on#
object#to#interface#value
// Interface returns v's value as an interface{}.
// func (v Value) Interface() interface{}
y := v.Interface().(float64) // y will have type float64
fmt.Println(y)
fmt.Printf("value is %7.1en", v.Interface()) // 3.4e+00
In#short,#the#Interface#method#is#the#inverse#of#the#
ValueOf#func6on,#except#that#its#result#is#always#of#
sta6c#type#interface{}.
Reitera6ng:#Reflec6on#goes#from#interface#values#to#
reflec6on#objects#and#back#again.
23. 3.#To#modify#a#reflec0on#object,#the#
value#must#be#se;able
var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.1) // Error: will panic.
// panic: reflect.Value.SetFloat using unaddressable value
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v:", v.CanSet())
// settability of v: false
What%is%"se$ability"?
25. "Use%the%pointer,%Luke."
var x float64 = 3.4
p := reflect.ValueOf(&x) // Note: take the address of x.
fmt.Println("type of p:", p.Type())
// type of p: *float64
fmt.Println("settability of p:", p.CanSet())
// settability of p: false
v := p.Elem()
fmt.Println("settability of v:", v.CanSet())
// settability of v: true
v.SetFloat(7.1)
fmt.Println(v.Interface())
// 7.1
fmt.Println(x)
// 7.1
26. Modifying)Structs
type T struct {
A int // Only exported fields are settable.
B string
}
t := T{23, "skidoo"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Printf("%d: %s %s = %vn", i,
typeOfT.Field(i).Name, f.Type(), f.Interface())
}
// "0: A int = 23" and "1: B string = skidoo"
s.Field(0).SetInt(77)
s.Field(1).SetString("Sunset Strip")
fmt.Println("t is now", t) // t is now {77 Sunset Strip}
31. Types
type ChanDir // A channel type's direction
func (d ChanDir) String() string
type Kind // The specific kind of type
func (k Kind) String() string
type Method // A single method
type SelectCase // A single select case
type SelectDir // The communication direction
type SliceHeader // A slice
type StringHeader // A string
type StructField // A single field in a struct
type StructTag // The tag in a struct field
func (tag StructTag) Get(key string) string
type Type // A Go type
type Value // A Go value
type ValueError // Error for Value
func (e *ValueError) Error() string
33. Type!interface
type Type interface {
Align() int
FieldAlign() int
Method(int) Method
MethodByName(string) (Method, bool)
NumMethod() int
Name() string
PkgPath() string
Size() uintptr
String() string
Kind() Kind
Implements(u Type) bool // Check if it implements Type u
AssignableTo(u Type) bool
ConvertibleTo(u Type) bool
...
34. Type!interface
...
Bits() int
ChanDir() ChanDir // for Chan
IsVariadic() bool // for ...argument
Elem() Type // for Array, Chan, Map, Ptr, or Slice
Field(i int) StructField // for Struct
FieldByIndex(index []int) StructField
FieldByName(name string) (StructField, bool)
FieldByNameFunc(match func(string) bool) (StructField, bool)
In(i int) Type // The i'th input of the function
Key() Type // for Map
Len() int // for Array
NumField() int // for Struct
NumIn() int // The number of the input of the function
NumOut() int // The number of the output of the function
Out(i int) Type // The i'th output of the function
}
35. Value!related!func,ons
func Append(s Value, x ...Value) Value
func AppendSlice(s, t Value) Value
func Indirect(v Value) Value
func MakeChan(typ Type, buffer int) Value
func MakeFunc(typ Type,
fn func(args []Value) (results []Value)) Value
func MakeMap(typ Type) Value
func MakeSlice(typ Type, len, cap int) Value
func New(typ Type) Value
func NewAt(typ Type, p unsafe.Pointer) Value
func ValueOf(i interface{}) Value
func Zero(typ Type) Value
36. Value!methods:!Type!and!kind
func (v Value) Addr() Value
func (v Value) Bool() bool
func (v Value) Bytes() []byte
func (v Value) Complex() complex128
func (v Value) Float() float64
func (v Value) Int() int64
func (v Value) Interface() (i interface{})
func (v Value) InterfaceData() [2]uintptr
func (v Value) Kind() Kind
func (v Value) Pointer() uintptr
func (v Value) Slice(i, j int) Value
func (v Value) Slice3(i, j, k int) Value
func (v Value) String() string
func (v Value) Type() Type
func (v Value) Uint() uint64
func (v Value) UnsafeAddr() uintptr
37. Value!methods:!Can_,!Is_!and!
Overflow_
func (v Value) CanAddr() bool
func (v Value) CanInterface() bool
func (v Value) CanSet() bool
func (v Value) IsNil() bool
func (v Value) IsValid() bool
func (v Value) OverflowComplex(x complex128) bool
func (v Value) OverflowFloat(x float64) bool
func (v Value) OverflowInt(x int64) bool
func (v Value) OverflowUint(x uint64) bool
39. Value!methods:!Channel
func (v Value) Recv() (x Value, ok bool)
func (v Value) Send(x Value)
func (v Value) TryRecv() (x Value, ok bool)
func (v Value) TrySend(x Value) bool
func (v Value) Close()
40. Value!methods:!Func.on!and!
method
func (v Value) Call(in []Value) []Value
func (v Value) CallSlice(in []Value) []Value
func (v Value) Method(i int) Value
func (v Value) MethodByName(name string) Value
func (v Value) NumMethod() int
41. Value!methods:!Field!of!struct
func (v Value) Field(i int) Value
func (v Value) FieldByIndex(index []int) Value
func (v Value) FieldByName(name string) Value
func (v Value) FieldByNameFunc(match func(string) bool) Value
func (v Value) NumField() int
42. Value!methods:!Se+ers
func (v Value) Set(x Value)
func (v Value) SetBool(x bool)
func (v Value) SetBytes(x []byte)
func (v Value) SetCap(n int)
func (v Value) SetComplex(x complex128)
func (v Value) SetFloat(x float64)
func (v Value) SetInt(x int64)
func (v Value) SetLen(n int)
func (v Value) SetMapIndex(key, val Value)
func (v Value) SetPointer(x unsafe.Pointer)
func (v Value) SetString(x string)
func (v Value) SetUint(x uint64)
48. Example:)codegangsta/inject
func (i *injector) Map(val interface{}) TypeMapper {
i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)
return i
}
func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {
i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)
return i
}
func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {
i.values[typ] = val
return i
}
49. Example:)codegangsta/inject
func (i *injector) Get(t reflect.Type) reflect.Value {
val := i.values[t]
if val.IsValid() {
return val
}
if t.Kind() == reflect.Interface {
for k, v := range i.values {
if k.Implements(t) {
val = v
break
}
}
}
if !val.IsValid() && i.parent != nil {
val = i.parent.Get(t)
}
return val
}