首页 文章资讯内容详情

Golang学习 - reflect 包

2026-06-01 4 花语

本文内容纲要:

------------------------------------------------------------ 在reflect包中,主要通过两个函数TypeOf()和ValueOf()实现反射,TypeOf()获取到的结果是reflect.Type类型,ValueOf()获取到的结果是reflect.Value类型,这两种类型都有很多方法可以进一步获取相关的反射信息。 这里有一个函数,可以获取指定对象的所有字段和方法: ------------------------------ //获取一个对象的字段和方法 packagemain import( "fmt" "reflect" ) //获取一个对象的字段和方法 funcGetMembers(iinterface{}){ //获取i的类型信息 t:=reflect.TypeOf(i) for{ //进一步获取i的类别信息 ift.Kind()==reflect.Struct{ //只有结构体可以获取其字段信息 fmt.Printf("\n%-8v%v个字段:\n",t,t.NumField()) //进一步获取i的字段信息 fori:=0;i<t.NumField();i++{ fmt.Println(t.Field(i).Name) } } //任何类型都可以获取其方法信息 fmt.Printf("\n%-8v%v个方法:\n",t,t.NumMethod()) //进一步获取i的方法信息 fori:=0;i<t.NumMethod();i++{ fmt.Println(t.Method(i).Name) } ift.Kind()==reflect.Ptr{ //如果是指针,则获取其所指向的元素 t=t.Elem() }else{ //否则上面已经处理过了,直接退出循环 break } } } //定义一个结构体用来进行测试 typesrstruct{ string } //接收器为实际类型 func(ssr)Read(){ } //接收器为指针类型 func(s*sr)Write(){ } funcmain(){ //测试 GetMembers(&sr{}) } /*测试结果(可以读取私有字段): *main.sr2个方法: Read Write main.sr1个字段: string main.sr1个方法: Read */ ------------------------------ 我们可以通过下面的代码获取reflect.Type的所有方法,以便进行学习: //reflect.Type是一个接口类型 GetMembers(new(reflect.Type)) 列出的方法并不一定通用,需要根据不同的类型选择使用,我们在这里给它们分一下类: ------------------------------ //通用 //获取t类型的字符串描述,不要通过String来判断两种类型是否一致。 func(t*rtype)String()string //获取t类型在其包中定义的名称,未命名类型则返回空字符串。 func(t*rtype)Name()string //获取t类型所在包的名称,未命名类型则返回空字符串。 func(t*rtype)PkgPath()string //获取t类型的类别。 func(t*rtype)Kind()reflect.Kind //获取t类型的值在分配内存时的大小,功能和unsafe.SizeOf一样。 func(t*rtype)Size()uintptr //获取t类型的值在分配内存时的字节对齐值。 func(t*rtype)Align()int //获取t类型的值作为结构体字段时的字节对齐值。 func(t*rtype)FieldAlign()int //获取t类型的方法数量。 func(t*rtype)NumMethod()int //根据索引获取t类型的方法,如果方法不存在,则panic。 //如果t是一个实际的类型,则返回值的Type和Func字段会列出接收者。 //如果t只是一个接口,则返回值的Type不列出接收者,Func为空值。 func(t*rtype)Method()reflect.Method //根据名称获取t类型的方法。 func(t*rtype)MethodByName(string)(reflect.Method,bool) //判断t类型是否实现了u接口。 func(t*rtype)Implements(ureflect.Type)bool //判断t类型的值可否转换为u类型。 func(t*rtype)ConvertibleTo(ureflect.Type)bool //判断t类型的值可否赋值给u类型。 func(t*rtype)AssignableTo(ureflect.Type)bool //判断t类型的值可否进行比较操作 func(t*rtype)Comparable()bool ------------------------------ //示例 typeinfinterface{ Method1() Method2() } typessstruct{ afunc() } func(iss)Method1(){} func(iss)Method2(){} funcmain(){ s:=reflect.TypeOf(ss{}) i:=reflect.TypeOf(new(inf)).Elem() Test(s) Test(i) } funcTest(treflect.Type){ ift.NumMethod()>0{ fmt.Printf("\n---%s---\n",t) fmt.Println(t.Method(0).Type) fmt.Println(t.Method(0).Func.String()) } } //输出结果: //---main.ss--- //func(main.ss) //<func(main.ss)Value> // //---main.inf--- //func() //<invalidValue> ------------------------------ //数值 //获取数值类型的位宽,t必须是整型、浮点型、复数型 func(t*rtype)Bits()int ------------------------------ //数组 //获取数组的元素个数 func(t*rtype)Len()int ------------------------------ //映射 //获取映射的键类型 func(t*rtype)Key()reflect.Type ------------------------------ //通道 //获取通道的方向 func(t*rtype)ChanDir()reflect.ChanDir ------------------------------ //结构体 //获取字段数量 func(t*rtype)NumField()int //根据索引获取字段 func(t*rtype)Field(int)reflect.StructField //根据名称获取字段 func(t*rtype)FieldByName(string)(reflect.StructField,bool) //根据指定的匹配函数math获取字段 func(t*rtype)FieldByNameFunc(matchfunc(string)bool)(reflect.StructField,bool) //根据索引链获取嵌套字段 func(t*rtype)FieldByIndex(index[]int)reflect.StructField ------------------------------ //函数 //获取函数的参数数量 func(t*rtype)NumIn()int //根据索引获取函数的参数信息 func(t*rtype)In(int)reflect.Type //获取函数的返回值数量 func(t*rtype)NumOut()int //根据索引获取函数的返回值信息 func(t*rtype)Out(int)reflect.Type //判断函数是否具有可变参数。 //如果有可变参数,则t.In(t.NumIn()-1)将返回一个切片。 func(t*rtype)IsVariadic()bool ------------------------------ //数组、切片、映射、通道、指针、接口 //获取元素类型、获取指针所指对象类型,获取接口的动态类型 func(t*rtype)Elem()reflect.Type ------------------------------ 下面的代码用到了所有这些方法: ------------------------------ //获取各种类型的相关信息 packagemain import( "fmt" "reflect" "unsafe" ) //嵌套结构体 typessstruct{ astruct{ int string } int string bool float64 } func(sss)Method1(iint)string{return"结构体方法1"} func(s*ss)Method2(iint)string{return"结构体方法2"} var( intValue=int(0) int8Value=int8(8) int16Value=int16(16) int32Value=int32(32) int64Value=int64(64) uIntValue=uint(0) uInt8Value=uint8(8) uInt16Value=uint16(16) uInt32Value=uint32(32) uInt64Value=uint64(64) byteValue=byte(0) runeValue=rune(0) uintptrValue=uintptr(0) boolValue=false stringValue="" float32Value=float32(32) float64Value=float64(64) complex64Value=complex64(64) complex128Value=complex128(128) arrayValue=[5]string{}//数组 sliceValue=[]byte{0,0,0,0,0}//切片 mapValue=map[string]int{}//映射 chanValue=make(chanint,2)//通道 structValue=ss{//结构体 struct{ int string }{10,"子结构体"}, 20, "结构体", false, 64.0, } func1Value=func(a,b,cint)string{//函数(固定参数) returnfmt.Sprintf("固定参数:%v%v%v",a,b,c) } func2Value=func(a,bint,c...int)string{//函数(动态参数) returnfmt.Sprintf("动态参数:%v%v%v",a,b,c) } unsafePointer=unsafe.Pointer(&structValue)//通用指针 reflectType=reflect.TypeOf(0)//反射类型 reflectValue=reflect.ValueOf(0)//反射值 reflectArrayValue=reflect.ValueOf([]int{1,2,3})//切片反射值 //反射接口类型 interfaceType=reflect.TypeOf(new(interface{})).Elem() ) //简单类型 varsimpleTypes=[]interface{}{ intValue,&intValue,//int int8Value,&int8Value,//int8 int16Value,&int16Value,//int16 int32Value,&int32Value,//int32 int64Value,&int64Value,//int64 uIntValue,&uIntValue,//uint uInt8Value,&uInt8Value,//uint8 uInt16Value,&uInt16Value,//uint16 uInt32Value,&uInt32Value,//uint32 uInt64Value,&uInt64Value,//uint64 byteValue,&byteValue,//byte runeValue,&runeValue,//rune uintptrValue,&uintptrValue,//uintptr boolValue,&boolValue,//bool stringValue,&stringValue,//string float32Value,&float32Value,//float32 float64Value,&float64Value,//float64 complex64Value,&complex64Value,//complex64 complex128Value,&complex128Value,//complex128 } //复杂类型 varcomplexTypes=[]interface{}{ arrayValue,&arrayValue,//数组 sliceValue,&sliceValue,//切片 mapValue,&mapValue,//映射 chanValue,&chanValue,//通道 structValue,&structValue,//结构体 func1Value,&func1Value,//定参函数 func2Value,&func2Value,//动参函数 structValue.Method1,structValue.Method2,//方法 unsafePointer,&unsafePointer,//指针 reflectType,&reflectType,//反射类型 reflectValue,&reflectValue,//反射值 interfaceType,&interfaceType,//接口反射类型 } //空值 varunsafePunsafe.Pointer //空接口 varnilInterfeceinterface{} funcmain(){ //测试简单类型 fori:=0;i<len(simpleTypes);i++{ PrintInfo(simpleTypes[i]) } //测试复杂类型 fori:=0;i<len(complexTypes);i++{ PrintInfo(complexTypes[i]) } //测试单个对象 PrintInfo(unsafeP) PrintInfo(&unsafeP) PrintInfo(nilInterfece) PrintInfo(&nilInterfece) } funcPrintInfo(iinterface{}){ ifi==nil{ fmt.Println("--------------------") fmt.Printf("无效接口值:%v\n",i) return } t:=reflect.TypeOf(i) PrintType(t) } funcPrintType(treflect.Type){ fmt.Println("--------------------") //-----通用方法----- fmt.Println("String:",t.String())//类型字符串 fmt.Println("Name:",t.Name())//类型名称 fmt.Println("PkgPath:",t.PkgPath())//所在包名称 fmt.Println("Kind:",t.Kind())//所属分类 fmt.Println("Size:",t.Size())//内存大小 fmt.Println("Align:",t.Align())//字节对齐 fmt.Println("FieldAlign:",t.FieldAlign())//字段对齐 fmt.Println("NumMethod:",t.NumMethod())//方法数量 ift.NumMethod()>0{ i:=0 for;i<t.NumMethod()-1;i++{ fmt.Println("┣",t.Method(i).Name)//通过索引定位方法 } fmt.Println("┗",t.Method(i).Name)//通过索引定位方法 } ifsm,ok:=t.MethodByName("String");ok{//通过名称定位方法 fmt.Println("MethodByName:",sm.Index,sm.Name) } fmt.Println("Implements(i{}):",t.Implements(interfaceType))//是否实现了指定接口 fmt.Println("ConvertibleTo(int):",t.ConvertibleTo(reflectType))//是否可转换为指定类型 fmt.Println("AssignableTo(int):",t.AssignableTo(reflectType))//是否可赋值给指定类型的变量 fmt.Println("Comparable:",t.Comparable())//是否可进行比较操作 //-----特殊类型----- switcht.Kind(){ //指针型: casereflect.Ptr: fmt.Println("===指针型===") //获取指针所指对象 t=t.Elem() fmt.Printf("转换到指针所指对象:%v\n",t.String()) //递归处理指针所指对象 PrintType(t) return //自由指针型: casereflect.UnsafePointer: fmt.Println("===自由指针===") //... //接口型: casereflect.Interface: fmt.Println("===接口型===") //... } //-----简单类型----- //数值型: ifreflect.Int<=t.Kind()&&t.Kind()<=reflect.Complex128{ fmt.Println("===数值型===") fmt.Println("Bits:",t.Bits())//位宽 } //-----复杂类型----- switcht.Kind(){ //数组型: casereflect.Array: fmt.Println("===数组型===") fmt.Println("Len:",t.Len())//数组长度 fmt.Println("Elem:",t.Elem())//数组元素类型 //切片型: casereflect.Slice: fmt.Println("===切片型===") fmt.Println("Elem:",t.Elem())//切片元素类型 //映射型: casereflect.Map: fmt.Println("===映射型===") fmt.Println("Key:",t.Key())//映射键 fmt.Println("Elem:",t.Elem())//映射值类型 //通道型: casereflect.Chan: fmt.Println("===通道型===") fmt.Println("ChanDir:",t.ChanDir())//通道方向 fmt.Println("Elem:",t.Elem())//通道元素类型 //结构体: casereflect.Struct: fmt.Println("===结构体===") fmt.Println("NumField:",t.NumField())//字段数量 ift.NumField()>0{ vari,jint //遍历结构体字段 fori=0;i<t.NumField()-1;i++{ field:=t.Field(i)//获取结构体字段 fmt.Printf("├%v\n",field.Name) //遍历嵌套结构体字段 iffield.Type.Kind()==reflect.Struct&&field.Type.NumField()>0{ forj=0;j<field.Type.NumField()-1;j++{ subfield:=t.FieldByIndex([]int{i,j})//获取嵌套结构体字段 fmt.Printf("│├%v\n",subfield.Name) } subfield:=t.FieldByIndex([]int{i,j})//获取嵌套结构体字段 fmt.Printf("│└%%v\n",subfield.Name) } } field:=t.Field(i)//获取结构体字段 fmt.Printf("└%v\n",field.Name) //通过名称查找字段 iffield,ok:=t.FieldByName("ptr");ok{ fmt.Println("FieldByName(ptr):",field.Name) } //通过函数查找字段 iffield,ok:=t.FieldByNameFunc(func(sstring)bool{returnlen(s)>3});ok{ fmt.Println("FieldByNameFunc:",field.Name) } } //函数型: casereflect.Func: fmt.Println("===函数型===") fmt.Println("IsVariadic:",t.IsVariadic())//是否具有变长参数 fmt.Println("NumIn:",t.NumIn())//参数数量 ift.NumIn()>0{ i:=0 for;i<t.NumIn()-1;i++{ fmt.Println("┣",t.In(i))//获取参数类型 } fmt.Println("┗",t.In(i))//获取参数类型 } fmt.Println("NumOut:",t.NumOut())//返回值数量 ift.NumOut()>0{ i:=0 for;i<t.NumOut()-1;i++{ fmt.Println("┣",t.Out(i))//获取返回值类型 } fmt.Println("┗",t.Out(i))//获取返回值类型 } } } ------------------------------------------------------------ 接下来学习reflect.Value的所有方法,还是进行分类学习,这里的很多操作(比如取地址、取切片、修改映射、通道进出、取值、赋值、函数调用等)和平时的操作都一样,只不过在这里需要用各种方法来操作,而平时只需要用一些符号来操作。 注意:下面描述的v值是指reflect.Value所代表的实际值,而不是reflect.Value本身。 ------------------------------ //特殊 //判断v值是否可寻址 //1、指针的Elem()可寻址 //2、切片的元素可寻址 //3、可寻址数组的元素可寻址 //4、可寻址结构体的字段可寻址,方法不可寻址 //也就是说,如果v值是指向数组的指针“&数组”,通过v.Elem()获取该指针指向的数组,那么 //该数组就是可寻址的,同时该数组的元素也是可寻址的,如果v就是一个普通数组,不是通过解引 //用得到的数组,那么该数组就不可寻址,其元素也不可寻址。结构体亦然。 func(vValue)CanAddr()bool //获取v值的地址,相当于&取地址操作。v值必须可寻址。 func(vValue)Addr()reflect.Value //判断v值是否可以被修改。只有可寻址的v值可被修改。 //结构体中的非导出字段(通过Field()等方法获取的)不能修改,所有方法不能修改。 func(vValue)CanSet()bool //判断v值是否可以转换为接口类型 //结构体中的非导出字段(通过Field()等方法获取的)不能转换为接口类型 func(vValue)CanInterface()bool //将v值转换为空接口类型。v值必须可转换为接口类型。 func(vValue)Interface()interface{} //使用一对uintptr返回接口的数据 func(vValue)InterfaceData()[2]uintptr ------------------------------ //示例: typessstruct{ Aint aint } func(sss)Method1(iint)string{return"结构体方法1"} func(s*ss)Method2(iint)string{return"结构体方法2"} funcmain(){ v1:=reflect.ValueOf(ss{})//结构体 v2:=reflect.ValueOf(&ss{})//结构体指针 v3:=reflect.ValueOf(&ss{}).Elem()//可寻址结构体 v4:=reflect.ValueOf(&ss{}).Elem().Field(0)//可寻址结构体的共有字段 v5:=reflect.ValueOf(&ss{}).Elem().Field(1)//可寻址结构体的私有字段 v6:=reflect.ValueOf(&ss{}).Method(0)//结构体指针的方法 v7:=reflect.ValueOf(&ss{}).Elem().Method(0)//结构体的方法 fmt.Println(v1.CanAddr())//false fmt.Println(v2.CanAddr())//false fmt.Println(v3.CanAddr())//true fmt.Println(v4.CanAddr())//true fmt.Println(v5.CanAddr())//true fmt.Println(v6.CanAddr())//false fmt.Println(v7.CanAddr())//false fmt.Println("----------") fmt.Println(v1.CanSet())//false fmt.Println(v2.CanSet())//false fmt.Println(v3.CanSet())//true fmt.Println(v4.CanSet())//true fmt.Println(v5.CanSet())//false fmt.Println(v6.CanSet())//false fmt.Println(v6.CanSet())//false fmt.Println("----------") fmt.Println(v1.CanInterface())//true fmt.Println(v2.CanInterface())//true fmt.Println(v3.CanInterface())//true fmt.Println(v4.CanInterface())//true fmt.Println(v5.CanInterface())//false fmt.Println(v6.CanInterface())//true fmt.Println(v7.CanInterface())//true } ------------------------------ //指针 //将v值转换为uintptr类型,v值必须是切片、映射、通道、函数、指针、自由指针。 func(vValue)Pointer()uintptr //获取v值的地址。v值必须是可寻址类型(CanAddr)。 func(vValue)UnsafeAddr()uintptr //将UnsafePointer类别的v值修改为x,v值必须是UnsafePointer类别,必须可修改。 func(vValue)SetPointer(xunsafe.Pointer) //判断v值是否为nil,v值必须是切片、映射、通道、函数、接口、指针。 //IsNil并不总等价于Go的潜在比较规则,比如对于variinterface{},i==nil将返回 //true,但是reflect.ValueOf(i).IsNil()将panic。 func(vValue)IsNil()bool //获取“指针所指的对象”或“接口所包含的对象” func(vValue)Elem()reflect.Value ------------------------------ //接口 //获取“指针所指的对象”或“接口所包含的对象” func(vValue)Elem()reflect.Value ------------------------------ //通用 //获取v值的字符串描述 func(vValue)String()string //获取v值的类型 func(vValue)Type()reflect.Type //返回v值的类别,如果v是空值,则返回reflect.Invalid。 func(vValue)Kind()reflect.Kind //获取v的方法数量 func(vValue)NumMethod()int //根据索引获取v值的方法,方法必须存在,否则panic //使用Call调用方法的时候不用传入接收者,Go会自动把v作为接收者传入。 func(vValue)Method(int)reflect.Value //根据名称获取v值的方法,如果该方法不存在,则返回空值(reflect.Invalid)。 func(vValue)MethodByName(string)reflect.Value //判断v本身(不是v值)是否为零值。 //如果v本身是零值,则除了String之外的其它所有方法都会panic。 func(vValue)IsValid()bool //将v值转换为t类型,v值必须可转换为t类型,否则panic。 func(vValue)Convert(tType)reflect.Value ------------------------------ //示例 funcmain(){ varvreflect.Value//未包含任何数据 fmt.Println(v.IsValid())//false vari*int v=reflect.ValueOf(i)//包含一个指针 fmt.Println(v.IsValid())//true v=reflect.ValueOf(nil)//包含一个nil指针 fmt.Println(v.IsValid())//false v=reflect.ValueOf(0)//包含一个int数据 fmt.Println(v.IsValid())//true } ------------------------------ //获取 //获取v值的内容,如果v值不是有符号整型,则panic。 func(vValue)Int()int64 //获取v值的内容,如果v值不是无符号整型(包括uintptr),则panic。 func(vValue)Uint()uint64 //获取v值的内容,如果v值不是浮点型,则panic。 func(vValue)Float()float64 //获取v值的内容,如果v值不是复数型,则panic。 func(vValue)Complex()complex128 //获取v值的内容,如果v值不是布尔型,则panic。 func(vValue)Bool()bool //获取v值的长度,v值必须是字符串、数组、切片、映射、通道。 func(vValue)Len()int //获取v值的容量,v值必须是数值、切片、通道。 func(vValue)Cap()int //获取v值的第i个元素,v值必须是字符串、数组、切片,i不能超出范围。 func(vValue)Index(iint)reflect.Value //获取v值的内容,如果v值不是字节切片,则panic。 func(vValue)Bytes()[]byte //获取v值的切片,切片长度=j-i,切片容量=v.Cap()-i。 //v必须是字符串、数值、切片,如果是数组则必须可寻址。i不能超出范围。 func(vValue)Slice(i,jint)reflect.Value //获取v值的切片,切片长度=j-i,切片容量=k-i。 //i、j、k不能超出v的容量。i<=j<=k。 //v必须是字符串、数值、切片,如果是数组则必须可寻址。i不能超出范围。 func(vValue)Slice3(i,j,kint)reflect.Value //根据key键获取v值的内容,v值必须是映射。 //如果指定的元素不存在,或v值是未初始化的映射,则返回零值(reflect.ValueOf(nil)) func(vValue)MapIndex(keyValue)reflect.Value //获取v值的所有键的无序列表,v值必须是映射。 //如果v值是未初始化的映射,则返回空列表。 func(vValue)MapKeys()[]reflect.Value //判断x是否超出v值的取值范围,v值必须是有符号整型。 func(vValue)OverflowInt(xint64)bool //判断x是否超出v值的取值范围,v值必须是无符号整型。 func(vValue)OverflowUint(xuint64)bool //判断x是否超出v值的取值范围,v值必须是浮点型。 func(vValue)OverflowFloat(xfloat64)bool //判断x是否超出v值的取值范围,v值必须是复数型。 func(vValue)OverflowComplex(xcomplex128)bool ------------------------------ //设置(这些方法要求v值必须可修改) //设置v值的内容,v值必须是有符号整型。 func(vValue)SetInt(xint64) //设置v值的内容,v值必须是无符号整型。 func(vValue)SetUint(xuint64) //设置v值的内容,v值必须是浮点型。 func(vValue)SetFloat(xfloat64) //设置v值的内容,v值必须是复数型。 func(vValue)SetComplex(xcomplex128) //设置v值的内容,v值必须是布尔型。 func(vValue)SetBool(xbool) //设置v值的内容,v值必须是字符串。 func(vValue)SetString(xstring) //设置v值的长度,v值必须是切片,n不能超出范围,不能为负数。 func(vValue)SetLen(nint) //设置v值的内容,v值必须是切片,n不能超出范围,不能小于Len。 func(vValue)SetCap(nint) //设置v值的内容,v值必须是字节切片。x可以超出v值容量。 func(vValue)SetBytes(x[]byte) //设置v值的键和值,如果键存在,则修改其值,如果键不存在,则添加键和值。 //如果将val设置为零值(reflect.ValueOf(nil)),则删除该键。 //如果v值是一个未初始化的map,则panic。 func(vValue)SetMapIndex(key,valreflect.Value) //设置v值的内容,v值必须可修改,x必须可以赋值给v值。 func(vValue)Set(xreflect.Value) ------------------------------ //结构体 //获取v值的字段数量,v值必须是结构体。 func(vValue)NumField()int //根据索引获取v值的字段,v值必须是结构体。如果字段不存在则panic。 func(vValue)Field(iint)reflect.Value //根据索引链获取v值的嵌套字段,v值必须是结构体。 func(vValue)FieldByIndex(index[]int)reflect.Value //根据名称获取v值的字段,v值必须是结构体。 //如果指定的字段不存在,则返回零值(reflect.ValueOf(nil)) func(vValue)FieldByName(string)reflect.Value //根据匹配函数match获取v值的字段,v值必须是结构体。 //如果没有匹配的字段,则返回零值(reflect.ValueOf(nil)) func(vValue)FieldByNameFunc(matchfunc(string)bool)Value ------------------------------ //示例 typessstruct{ sstruct{ Bint bint } Aint aint } funcmain(){ varv=reflect.ValueOf(ss{}) fori:=0;i<v.NumField();i++{ field:=v.Field(i) fmt.Println("字段:",field.Type().String()) iffield.Type().Kind()==reflect.Struct{ forj:=0;j<field.NumField();j++{ subfield:=field.Field(j) fmt.Println("嵌套字段:",subfield.Type().String()) } } } } //输出结果: //字段:struct{Bint;bint} //嵌套字段:int //嵌套字段:int //字段:int //字段:int ------------------------------ //通道 //发送数据(会阻塞),v值必须是可写通道。 func(vValue)Send(xreflect.Value) //接收数据(会阻塞),v值必须是可读通道。 func(vValue)Recv()(xreflect.Value,okbool) //尝试发送数据(不会阻塞),v值必须是可写通道。 func(vValue)TrySend(xreflect.Value)bool //尝试接收数据(不会阻塞),v值必须是可读通道。 func(vValue)TryRecv()(xreflect.Value,okbool) //关闭通道,v值必须是通道。 func(vValue)Close() ------------------------------ //示例 funcmain(){ ch:=make(chanint,2) v:=reflect.ValueOf(ch) a:=reflect.ValueOf(1) b:=reflect.ValueOf(2) v.Send(a) ifok:=v.TrySend(b);ok{ fmt.Println("尝试发送成功!")//尝试发送成功! } ifi,ok:=v.Recv();ok{ fmt.Println("接收成功:",i)//接收成功:1 } ifi,ok:=v.TryRecv();ok{ fmt.Println("尝试接收成功:",i)//尝试接收成功:2 } } ------------------------------ //函数 //通过参数列表in调用v值所代表的函数(或方法)。函数的返回值存入r中返回。 //要传入多少参数就在in中存入多少元素。 //Call即可以调用定参函数(参数数量固定),也可以调用变参函数(参数数量可变)。 func(vValue)Call(in[]Value)(r[]Value) //通过参数列表in调用v值所代表的函数(或方法)。函数的返回值存入r中返回。 //函数指定了多少参数就在in中存入多少元素,变参作为一个单独的参数提供。 //CallSlice只能调用变参函数。 func(vValue)CallSlice(in[]Value)[]Value ------------------------------ //示例 varf1=func(aint,b[]int){fmt.Println(a,b)} varf2=func(aint,b...int){fmt.Println(a,b)} funcmain(){ v1:=reflect.ValueOf(f1) v2:=reflect.ValueOf(f2) a:=reflect.ValueOf(1) b:=reflect.ValueOf([]int{1,2,3}) v1.Call([]reflect.Value{a,b}) v2.Call([]reflect.Value{a,a,a,a,a,a}) //v1.CallSlice([]reflect.Value{a,b})//非变参函数,不能用CallSlice。 v2.CallSlice([]reflect.Value{a,b}) } ------------------------------ 下面的代码用到了所有这些方法: ------------------------------ //获取各种值的相关信息 packagemain import( "fmt" "reflect" "unsafe" ) //嵌套结构体 typessstruct{ astruct{ int string } int string bool float64 } func(sss)Method1(iint)string{return"结构体方法1"} func(s*ss)Method2(iint)string{return"结构体方法2"} var( intValue=int(0) int8Value=int8(8) int16Value=int16(16) int32Value=int32(32) int64Value=int64(64) uIntValue=uint(0) uInt8Value=uint8(8) uInt16Value=uint16(16) uInt32Value=uint32(32) uInt64Value=uint64(64) byteValue=byte(0) runeValue=rune(0) uintptrValue=uintptr(0) boolValue=false stringValue="stringValue" float32Value=float32(32) float64Value=float64(64) complex64Value=complex64(64) complex128Value=complex128(128) arrayValue=[5]string{}//数组 sliceValue=[]byte{0,0,0,0,0}//切片 mapValue=map[string]int{}//映射 chanValue=make(chanint,2)//通道 structValue=ss{//结构体 struct{ int string }{10,"子结构体"}, 20, "结构体", false, 64.0, } func1Value=func(iint)string{//函数(固定参数) returnfmt.Sprintf("固定参数:%v",i) } func2Value=func(i...int)string{//函数(动态参数) returnfmt.Sprintf("动态参数:%v",i) } unsafePointer=unsafe.Pointer(&structValue)//通用指针 reflectType=reflect.TypeOf(0)//反射类型 reflectValue=reflect.ValueOf(0)//反射值 reflectArrayValue=reflect.ValueOf([]int{1,2,3})//切片反射值 //反射接口类型 interfaceType=reflect.TypeOf(new(interface{})).Elem() ) //简单类型 varsimpleTypes=[]interface{}{ intValue,&intValue,//int int8Value,&int8Value,//int8 int16Value,&int16Value,//int16 int32Value,&int32Value,//int32 int64Value,&int64Value,//int64 uIntValue,&uIntValue,//uint uInt8Value,&uInt8Value,//uint8 uInt16Value,&uInt16Value,//uint16 uInt32Value,&uInt32Value,//uint32 uInt64Value,&uInt64Value,//uint64 byteValue,&byteValue,//byte runeValue,&runeValue,//rune uintptrValue,&uintptrValue,//uintptr boolValue,&boolValue,//bool stringValue,&stringValue,//string float32Value,&float32Value,//float32 float64Value,&float64Value,//float64 complex64Value,&complex64Value,//complex64 complex128Value,&complex128Value,//complex128 } //复杂类型 varcomplexTypes=[]interface{}{ arrayValue,&arrayValue,//数组 sliceValue,&sliceValue,//切片 mapValue,&mapValue,//映射 chanValue,&chanValue,//通道 structValue,&structValue,//结构体 func1Value,&func1Value,//定参函数 func2Value,&func2Value,//动参函数 structValue.Method1,structValue.Method2,//方法 unsafePointer,&unsafePointer,//指针 reflectType,&reflectType,//反射类型 reflectValue,&reflectValue,//反射值 interfaceType,&interfaceType,//接口反射类型 } //空值 varunsafePunsafe.Pointer //空接口 varnilInterfeceinterface{} funcmain(){ //测试简单类型 fori:=0;i<len(simpleTypes);i++{ PrintInfo(simpleTypes[i]) } //测试复杂类型 fori:=0;i<len(complexTypes);i++{ PrintInfo(complexTypes[i]) } //测试单个对象 PrintInfo(&unsafeP) PrintInfo(nilInterfece) //PrintInfo(&nilInterfece)//会引发panic } funcPrintInfo(iinterface{}){ ifi==nil{ fmt.Println("--------------------") fmt.Printf("无效接口值:%v\n",i) fmt.Println("--------------------") return } v:=reflect.ValueOf(i) PrintValue(v) } funcPrintValue(vreflect.Value){ fmt.Println("--------------------") //-----通用方法----- fmt.Println("String:",v.String())//反射值的字符串形式 fmt.Println("Type:",v.Type())//反射值的类型 fmt.Println("Kind:",v.Kind())//反射值的类别 fmt.Println("CanAddr:",v.CanAddr())//是否可以获取地址 fmt.Println("CanSet:",v.CanSet())//是否可以修改 ifv.CanAddr(){ fmt.Println("Addr:",v.Addr())//获取地址 fmt.Println("UnsafeAddr:",v.UnsafeAddr())//获取自由地址 } //是否可转换为接口对象 fmt.Println("CanInterface:",v.CanInterface()) ifv.CanInterface(){ fmt.Println("Interface:",v.Interface())//转换为接口对象 } //获取方法数量 fmt.Println("NumMethod:",v.NumMethod()) ifv.NumMethod()>0{ //遍历方法 i:=0 for;i<v.NumMethod()-1;i++{ fmt.Printf("┣%v\n",v.Method(i).String()) // ifi>=4{//只列举5个 // fmt.Println("┗...") // break // } } fmt.Printf("┗%v\n",v.Method(i).String()) //通过名称获取方法 fmt.Println("MethodByName:",v.MethodByName("String").String()) } //-----可获取指针的类型----- switchv.Kind(){ casereflect.Slice,reflect.Map,reflect.Chan,reflect.Func, reflect.Ptr,reflect.UnsafePointer: fmt.Println("Pointer:",v.Pointer()) } //-----特殊类型----- switchv.Kind(){ //指针: casereflect.Ptr: fmt.Println("===指针===") //获取指针地址 if!v.IsNil(){ //获取指针所指对象 v=v.Elem()//只有指针和接口类型可以使用Elem() fmt.Printf("转换到指针所指对象:%v\n",v.Type()) //递归处理指针所指对象 PrintValue(v) return } //自由指针: casereflect.UnsafePointer: fmt.Println("===自由指针===") ifv.Pointer()==0{ v.SetPointer(unsafePointer) fmt.Println("重新指向新对象:",v.Pointer()) } //将自由指针转换为*ss指针(因为定义unsafePointer时已经确定了类型) s:=(*ss)(v.Interface().(unsafe.Pointer)) //获取反射值 v=reflect.ValueOf(s) if!v.IsNil(){ //获取指针所指对象 v=v.Elem()//只有指针和接口类型可以使用Elem() fmt.Printf("转换到指针所指对象:%v\n",v.Type()) //递归处理指针所指对象 PrintValue(v) return } //接口: casereflect.Interface: fmt.Println("===接口===") //获取接口数据 fmt.Println("InterfaceData:",v.InterfaceData()) //获取接口所包含的对象 v=v.Elem()//只有指针和接口类型可以使用Elem() fmt.Printf("转换到接口所含对象:%v\n",v.Type()) //递归处理接口的动态对象 PrintValue(v) return } //-----简单类型----- //有符号整型: ifreflect.Int<=v.Kind()&&v.Kind()<=reflect.Int64{ fmt.Println("===有符号整型===") fmt.Println("Int:",v.Int())//获取值 ifv.CanSet(){ v.SetInt(10)//设置值 fmt.Println("Int:",v.Int())//获取值 v.Set(reflect.ValueOf(20).Convert(v.Type()))//设置值 } fmt.Println("Int:",v.Int())//获取值 fmt.Println("OverflowInt:",v.OverflowInt(10))//是否溢出 } //无符号整型: ifreflect.Uint<=v.Kind()&&v.Kind()<=reflect.Uint64{ fmt.Println("===无符号整型===") fmt.Println("Uint:",v.Uint())//获取值 ifv.CanSet(){ v.SetUint(10)//设置值 fmt.Println("Uint:",v.Uint())//获取值 v.Set(reflect.ValueOf(20).Convert(v.Type()))//设置值 } fmt.Println("Uint:",v.Uint())//获取值 fmt.Println("OverflowUint:",v.OverflowUint(10))//是否溢出 } switchv.Kind(){ //浮点数: casereflect.Float32,reflect.Float64: fmt.Println("===浮点数===") fmt.Println("Float:",v.Float())//获取值 ifv.CanSet(){ v.SetFloat(10)//设置值 fmt.Println("Float:",v.Float())//获取值 v.Set(reflect.ValueOf(20).Convert(v.Type()))//设置值 } fmt.Println("Float:",v.Float())//获取值 fmt.Println("OverflowFloat:",v.OverflowFloat(10))//是否溢出 //复数: casereflect.Complex64,reflect.Complex128: fmt.Println("===复数===") fmt.Println("Complex:",v.Complex())//获取值 ifv.CanSet(){ v.SetComplex(10)//设置值 fmt.Println("Complex:",v.Complex())//获取值 v.Set(reflect.ValueOf(20+20i).Convert(v.Type()))//设置值 } fmt.Println("Complex:",v.Complex())//获取值 fmt.Println("OverflowComplex:",v.OverflowComplex(10))//是否溢出 //布尔型: casereflect.Bool: fmt.Println("===布尔型===") fmt.Println("Bool:",v.Bool())//获取值 ifv.CanSet(){ v.SetBool(true)//设置值 fmt.Println("Bool:",v.Bool())//获取值 v.Set(reflect.ValueOf(false))//设置值 } fmt.Println("Bool:",v.Bool())//获取值 //字符串: casereflect.String: fmt.Println("===字符串===") fmt.Println("String:",v.String())//获取值 ifv.CanSet(){ v.SetString("abc")//设置值 fmt.Println("String:",v.String())//获取值 v.Set(reflect.ValueOf("def"))//设置值 } fmt.Println("String:",v.String())//获取值 //-----复杂类型----- //切片型: casereflect.Slice: fmt.Println("===切片型===") fmt.Println("Len:",v.Len())//获取长度 fmt.Println("Cap:",v.Cap())//获取容量 ifv.CanSet(){ v.SetLen(4)//不能大于cap v.SetCap(4)//不能小于len,只能缩,不能扩 fmt.Println("SetLen,SetCap:",v.Len(),v.Cap()) //重新指定字节内容 ifv.Type().Elem().Kind()==reflect.Uint8{ v.SetBytes([]byte{1,2,3,4,5,6,7,8,9,0}) } fmt.Println("SetByte:",[]byte{1,2,3,4,5,6,7,8,9,0}) } //获取字节内容 ifv.Type().Elem().Kind()==reflect.Uint8{ fmt.Println("Bytes:",v.Bytes()) } //根据索引获取元素 ifv.Len()>0{ fori:=0;i<v.Len();i++{ fmt.Println("Index:",v.Index(i)) } } //获取一个指定范围的切片 //参数:起始下标,结束下标 //长度=结束下标-起始下标 s1:=v.Slice(1,2) fmt.Println("Slice:",s1) fmt.Println("Len:",s1.Len())//获取长度 fmt.Println("Cap:",s1.Cap())//获取容量 //获取一个指定范围和容量的切片 //参数:起始下标,结束下标,容量下标 //长度=结束下标-起始下标 //容量=容量下标-起始下标 s2:=v.Slice3(1,2,4) fmt.Println("Slice:",s2) fmt.Println("Len:",s2.Len())//获取长度 fmt.Println("Cap:",s2.Cap())//获取容量 //映射型: casereflect.Map: fmt.Println("===映射型===") //设置键值,不需要检测CanSet v.SetMapIndex(reflect.ValueOf("a"),reflect.ValueOf(1)) v.SetMapIndex(reflect.ValueOf("b"),reflect.ValueOf(2)) v.SetMapIndex(reflect.ValueOf("c"),reflect.ValueOf(3)) //获取键列表 fmt.Println("MapKeys:",v.MapKeys()) for_,idx:=rangev.MapKeys(){ //根据键获取值 fmt.Println("MapIndex:",v.MapIndex(idx)) } //结构体: casereflect.Struct: fmt.Println("===结构体===") //获取字段个数 fmt.Println("NumField:",v.NumField()) ifv.NumField()>0{ vari,jint //遍历结构体字段 fori=0;i<v.NumField()-1;i++{ field:=v.Field(i)//获取结构体字段 fmt.Printf("├%-8v%v\n",field.Type(),field.String()) //遍历嵌套结构体字段 iffield.Kind()==reflect.Struct&&field.NumField()>0{ forj=0;j<field.NumField()-1;j++{ subfield:=v.FieldByIndex([]int{i,j})//获取嵌套结构体字段 fmt.Printf("│├%-8v%v\n",subfield.Type(),subfield.String()) //ifi>=4{//只列举5个 // fmt.Println("┗...") // break //} } subfield:=v.FieldByIndex([]int{i,j})//获取嵌套结构体字段 fmt.Printf("│└%-8v%v\n",subfield.Type(),subfield.String()) } //ifi>=4{//只列举5个 // fmt.Println("┗...") // break //} } field:=v.Field(i)//获取结构体字段 fmt.Printf("└%-8v%v\n",field.Type(),field.String()) //通过名称查找字段 ifv:=v.FieldByName("ptr");v.IsValid(){ fmt.Println("FieldByName(ptr):",v.Type().Name()) } //通过函数查找字段 v:=v.FieldByNameFunc(func(sstring)bool{returnlen(s)>3}) ifv.IsValid(){ fmt.Println("FieldByNameFunc:",v.Type().Name()) } } //通道型: casereflect.Chan: fmt.Println("===通道型===") //发送数据(会阻塞) v.Send(reflectValue) //尝试发送数据(不会阻塞) fmt.Println("TrySend:",v.TrySend(reflectValue)) //接收数据(会阻塞) ifx,ok:=v.Recv();ok{ fmt.Println("Recv:",x)// } //尝试接收数据(不会阻塞) ifx,ok:=v.TryRecv();ok{ fmt.Println("TryRecv:",x)// } //因为要执行两次,通道和通道指针各执行一次,关闭后第二次就无法执行了。 //v.Close() //函数型: casereflect.Func: fmt.Println("===函数型===") //判断函数是否具有变长参数 ifv.Type().IsVariadic(){ //与可变参数对应的实参必须是切片类型的反射值(reflectArrayValue)。 fmt.Println("CallSlice:",v.CallSlice([]reflect.Value{reflectArrayValue}))// //也可以用v.Call调用变长参数的函数,只需传入reflectValue即可。 }else{ //根据函数定义的参数数量,传入相应数量的反射值(reflectValue)。 fmt.Println("Call:",v.Call([]reflect.Value{reflectValue}))// } } } ------------------------------------------------------------

本文内容总结:

原文链接:https://www.cnblogs.com/golove/p/5909541.html