反射包主要有一個接口: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類型方法介紹
- func (t *commonType) Align() int
- 類型在內容分配時,返回的字節的對齊方式
- func (t *commonType) FieldAlign() int
- 當類型作為一個結構的字段時,他的字節對齊方式
- func (t *commonType) Method(i int) (m Method)
-
通過整形索引,反射類型的方法,返回一個Method類型
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 }
- func (t *commonType) MethodByName(name string) (m Method, ok bool)
-
通過方法名,判斷該類型是否有該方法,如果存在返回該方法,並且返回ok值為true
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) }
- func (t *commonType) NumMethod() int
- 返回該類型擁有的方法數量
- func (t *commonType) Name() string
- 返回類型的名稱,如果是匿名類型將返回空字符竄,如果是指針,則什么都沒有
- func (t *commonType) PkgPath() string
- 返回類型所在包的路徑,如果是指針則什么都木有
- func (t *commonType) Size() uintptr
- 返回類型的大小
- func (t *commonType) String() string
- 返回類型的字符竄名稱
- func (t *commonType) Kind() Kind
- 返回這個類型的特殊種類,(struct,ptr,func等)
- func (t *commonType) Implements(u Type) bool
- 判斷類型是否實現u這個接口.注意u必須不能為nil,且是一個接口
- func (t *commonType) AssignableTo(u Type) bool
- 判斷類型是否可分配到u類型
- func (t *commonType) Bits() int
- 反射類型的使用字節,如果不是Int,Uint,Float,complex種類則會產生恐慌
- func (t *commonType) ChanDir() ChanDir
- 反射channel 目錄
- func (t *commonType) IsVariadic() bool
-
判斷函數是否有可變參數(...)
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 }
- func (t *commonType) Elem() Type
-
返回一個類型的元素類型,種類非Array,chan,map,ptr,slice會產生恐慌
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 }
- func (t *commonType) Field(i int) StructField
- 根據索引返回一個結構的字段,值為StructField類型
- func (t *commonType) FieldByIndex(index []int) StructField
-
返回嵌套類型的字段結構.
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 }
- func (t *commonType) FieldByName(name string) (StructField, bool)
- 根據字段名,反射該字段類型
- func (t *commonType) FieldByNameFunc(match func(string) bool) (StructField, bool)
- ....沒明白
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 (t *commonType) In(i int) Type
-
反射函數類型的第i個參數
func test(a string) bool { return true } func main() { fmt.Println(reflect.TypeOf(test).In(0)) }
- func (t *commonType) Key() Type
- 反射map類型的key的類型,如果不是map則會產生恐慌
- func (t *commonType) Len() int
- 反射array類型的長度,如果不是array,則會產生恐慌
- func (t *commonType) NumField() int
- 反射一個struct的字段數量,如果不是struct則會產生恐慌
- func (t *commonType) NumIn() int
- 反射一個func的輸入參數的數量,如果不是函數則會產生恐慌
- func (t *commonType) NumOut() int
- 反射函數的返回結果的數量,入股不是函數則會產生恐慌
- func (t *commonType) Out(i int) Type
- 反射函數返回結果的i的類型,如果不是函數則產生恐慌,而且如果不在范圍[0, NumOut()]則也會產生恐慌
題外話:聲明變量其值為匿名結構
type T struct {} var t T var t struct {}