反射包主要有一个接口: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 {}