首页 文章资讯内容详情

golang reflect

2026-06-01 4 花语

本文内容纲要:

-golangreflect -接口值到反射对象 -反射对象到接口值 -修改反射对象 -获取结构体标签 -interface{}到函数反射

golangreflect

go语言中reflect反射机制。详细原文:地址

接口值到反射对象

packagemain import( "fmt" "reflect" ) funcmain(){ varxint=1 fmt.Println("type:",reflect.TypeOf(x)) } type:int

TypeOf函数的定义如下,参数为接口类型,返回值为类型

funcTypeOf(iinterface{})Type

ValueOf函数的定义如下,参数为接口类型,返回值为Value

varxint=1 fmt.Println("value:",reflect.ValueOf(x)) value:<intValue>

可以通过Kind函数来检查类型,

fmt.Println("Kind:",reflect.ValueOf(x).Kind()) fmt.Println("KindisInt?",reflect.ValueOf(x).Kind()==reflect.int) Kind:int KindisInt?true

反射对象到接口值

通过Interface函数可以实现反射对象到接口值的转换,

func(vValue)Interface()interface{} //Interface以interface{}返回v的值 y:=v.Interface().(float64) fmt.Println(y)

修改反射对象

修改反射对象的前提条件是其值必须是可设置的

varxfloat64=3.4 v:=reflect.ValueOf(x) v.SetFloat(7.3)//Error:panic

为了避免这个问题,需要使用CanSet函数来检查该值的设置性,

varxfloat64=3.4 v:=reflect.ValueOf(x) fmt.Println("settabilityofv:",v.CanSet()) settabilityofv:false

那么如何才能设置该值呢?

这里需要考虑一个常见的问题,参数传递,传值还是传引用或地址?

在上面的例子中,我们使用的是reflect.ValueOf(x),这是一个值传递,传递的是x的值的一个副本,不是x本身,因此更新副本中的值是不允许的。如果使用reflect.ValueOf(&x)来替换刚才的值传递,就可以实现值的修改。 varxfloat64=3.4 p:=reflect.ValueOf(&x)//获取x的地址 fmt.Println("settabilityofp:",p.CanSet()) v:=p.Elem() fmt.Println("settabilityofv:",v.CanSet()) v.SetFloat(7.1) fmt.Println(v.Interface()) fmt.Println(x) settabilityofp:false settabilityofv:true 7.1 7.1

获取结构体标签

首先介绍如何遍历结构体字段内容,

假设结构体如下, typeTstruct{ Aint Bstring } t:=T{12,"skidoo"}

从而,通过反射来遍历所有的字段内容

s:=reflect.ValueOf(&t).Elem() typeOfT:=s.Type() fori:=0;i<s.NumField();i++{ f:=s.Field(i) fmt.Printf("%d%s%s=%v\n",i,typeOfT.Field(i).Name,f.Type(),f.Interface()) } 0Aint=23 1Bstring=skidoo

接下来,如何获取结构体的标签内容?

funcmain(){ typeSstruct{ Fstring`species:"gopher"color:"blue"` } s:=S{} st:=reflect.TypeOf(s) field:=st.Field(0) fmt.Println(field.Tag.Get("color"),field.Tag.Get("species")) }

interface{}到函数反射

一般情况下,为了存储多个函数值,一般采用map来存储。其中key为函数名称,而value为相应的处理函数。

在这里需要定义好函数类型,但是函数的参数以及返回类型就需要是统一的,如下 packagemain import"fmt" funcsay(textstring){ fmt.Println(text) } funcmain(){ varfuncMap=make(map[string]func(string)) funcMap["say"]=say funcMap["say"]("hello") }

如果希望map可以存储任意类型的函数(参数不同,返回值不同),那么就需要用interface{}而不是func(param...)来定义value。

packagemain import"fmt" funcsay(textstring){ fmt.Println(text) } funcmain(){ varfuncMap=make(map[string]interface{}) funcMap["say"]=say funcMap["say"]("hello") } cannotcallnon-functionfuncMap["say"](typeinterface{})

直接调用会报错,提示不能调用interface{}类型的函数。

这时,需要利用reflect把函数从interface转换到函数来使用,

packagemain import( "fmt" "reflect" ) funcsay(textstring){ fmt.Println(text) } funcCall(mmap[string]interface{},namestring,params...interface{})(result[]reflect.Value){ f:=reflect.ValueOf(m[name]) in:=make([]reflect.Value,len(params)) fork,param:=rangeparams{ in[k]=reflect.ValueOf(param) } result=f.Call(in) return } funcmain(){ varfuncMap=make(map[string]interface{}) funcMap["say"]=say Call(funcMap,"say","hello")

本文内容总结:golangreflect,接口值到反射对象,反射对象到接口值,修改反射对象,获取结构体标签,interface{}到函数反射,

原文链接:https://www.cnblogs.com/coder2012/p/4881854.html