• 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 {}
    
    
  • 相关阅读:
    Java通过反射加载的类,变量无法注入
    jmeter http并发测试时报错
    spring 自定义注解
    cmd 和powershell 用git 显示乱码
    centos6.8上安装部署 jhipster-registry
    tcpdf最新版 6.2版
    微信Oauth2.0鉴权 40029 问题
    微信支付学习记录1
    win10 localhost 解析为 ipv6地址 ::1 的解决办法
    PHPExcel 导出时乱码
  • 原文地址:https://www.cnblogs.com/zhepama/p/3008554.html
Copyright © 2020-2023  润新知