這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
反射包主要有一個介面: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 stringPkgPath stringType Type // method typeFunc Value // func with receiver as first argumentIndex int // index for Type.Method}
structField結構
Field()和FieldByIndex(),以及FieldByName(),FieldByNameFunc會返回該類型
type structField struct {name *string // nil for embedded fieldspkgPath *string // nil for exported Names; otherwise import pathtyp *runtimeType // type of fieldtag *string // nil if no tagoffset 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 stringb bytea 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 stringb bytea 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
-
傳回型別的名稱,如果是匿名型別將返回Null 字元竄,如果是指標,則什麼都沒有
-
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 stringb bytea int}func (b B) test() {}func test(a ...int) {}func main() {fmt.Println(reflect.TypeOf(test).IsVariadic()) //truefmt.Println(reflect.TypeOf(B.test).IsVariadic()) //false}
-
func (t *commonType) Elem() Type
-
返回一個類型的元素類型,種類非Array,chan,map,ptr,slice會產生恐慌
type B struct {c stringb bytea 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 intb bytec string}type B struct {Ac stringb bytea 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 stringb bytea 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 Tvar t struct {}