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 {}

本文来自:博客园

感谢作者:zhepama

查看原文:golang的反射-Type

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。