反射包主要有一个接口:type,和一个结构value;
type接口
commonType类型实现了type接口,下面是type中的各类型关系
- commonType>unCommonType>method
- arrayType|chanType|funcType|interfaceType|mapType|ptrType|sliceType >commonType
- ptrMap>n*commonType
其他结构
Method结构
MethodByName()和Method()会返回这种类型
type Method struct { Name string PkgPath string Type Type // method type Func Value // func with receiver as first argument Index int // index for Type.Method }
structField结构
Field()和FieldByIndex(),以及FieldByName(),FieldByNameFunc会返回该类型
type structField struct { name *string // nil for embedded fields pkgPath *string // nil for exported Names; otherwise import path typ *runtimeType // type of field tag *string // nil if no tag offset uintptr // byte offset of field within struct }
反射一个变量的type,本质上是将这个变量的指针转换为commonType的指针
- 首先将变量的指针,通过unsafe包将类型转换为Pointer类型
- 然后将Pointer类型转换为*emptyInterface类型,并使用*表达式将其emptyInterface的值传给eface
- 断言eface.typ的值是否是commonType的指针类型,如果是则返回其值
func toType(p *runtimeType) Type { if p == nil { return nil } return (*p).(*commonType) } func TypeOf(i interface{}) Type { eface := *(*emptyInterface)(unsafe.Pointer(&i)) return toType(eface.typ) }
类型函数介绍
- func ChanOf(dir ChanDir, t Type) Type
- 返回channel type
- func MapOf(key, elem Type) Type
- 返回Map type
- func PtrTo(t Type) Type
- 返回指针类型
- func SliceOf(t Type) Type
- 返回slice类型
- func TypeOf(i interface{}) Type
- 反射变量类型,最好不要直接传指针进去.否则会有些东西发射不出.例如Name()
type类型方法介绍
type B struct { c string b byte a int } func (b B) test() { } func main() { b := B{} fmt.Println(reflect.TypeOf(b).Method(0).Name) //test }
type B struct { c string b byte a int } func (b B) test() { } func main() { b := new(B) m, _ := reflect.TypeOf(b).MethodByName("test") fmt.Println(m.PkgPath) }
type B struct { c string b byte a int } func (b B) test() { } func test(a ...int) { } func main() { fmt.Println(reflect.TypeOf(test).IsVariadic()) //true fmt.Println(reflect.TypeOf(B.test).IsVariadic()) //false }
type B struct { c string b byte a int } func (b B) test() { } func main() { b := &B{} fmt.Println(reflect.TypeOf(b).Elem()) //main.B }
type A struct { a int b byte c string } type B struct { A c string b byte a int } func (b B) test() { } func main() { b := B{} index := []int{0, 1} fmt.Println(reflect.TypeOf(b).FieldByIndex(index).Name) //b }
type B struct { c string b byte a int } func test(a string) bool { return true } func main() { b := B{} fmt.Println(reflect.TypeOf(b).FieldByNameFunc(test)) //{ 0 [] false} false }
func test(a string) bool { return true } func main() { fmt.Println(reflect.TypeOf(test).In(0)) }
题外话:声明变量其值为匿名结构
type T struct {} var t T var t struct {}