golang的反射-Type


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM