GO之反射
Posted louis181214
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了GO之反射相关的知识,希望对你有一定的参考价值。
一:反射的基本介绍
①:反射可以在运行时动态获取变量的各种信息,比如变量的类型(type),类别(kind);
②:如果是结构体变量,还可以获取结构体声明的字段好方法;
③:通过反射,可以修改变量的值,可以钓鱼关联的方法;
④:反射,需要import "reflect"
二:反射的应用场景
①:不知道接口调用哪个函数,根据传入参数在运行时确定调用的具体接口,这种需要对函数或方法反射;
②:对结构体的序列化时,如果结构体有指定tag,也会用到反射(go底层完成反射操作)。
三:反射重要的函数和概念
①:reflect.TypeOf(变量名),获取变量的类型,返回reflect.type类型;
②:reflect.ValueOf(变量名),获取变量的值,返回reflect.Value类型,reflect.Value是一个结构体,通过该结构体可以获取变量的更多信息;
③:变量,interface{}和reflect.Value是可以相互转化
四:反射的使用举例
package main import ( "fmt" "reflect" ) //基本数据的反射 func reflectInt(i interface{}){ //获取变量的type和kind值 re_int_type := reflect.TypeOf(i) fmt.Printf("re_int_type=%v ", re_int_type) //获取变量的值信息 re_int_value := reflect.ValueOf(i) fmt.Printf("re_int_value=%T,re_int_value=%v ", re_int_value, re_int_value) //不可以直接使用re_int_value,因为re_int_value实际上是reflect.Value类型并不是int num := 10 + re_int_value.Int() fmt.Printf("num=%v ", num) //将re_int_value转为interface{} inter_value := re_int_value.Interface() //由于变量本身就是int型,故interface{}显示为int fmt.Printf("inter_value=%v,inter_value type=%T ", inter_value, inter_value) //再转换成interface{}后,只要通过断言就可转换成其他数据类型 int_value, ok := inter_value.(int) if ok { fmt.Printf("int_value=%v,int_value type=%T ", int_value, int_value) } } func main() { var number int = 10 reflectInt(number) } 结果 [ `go run reflect.go` | done ] re_int_type=int re_int_value=reflect.Value,re_int_value=10 num=20 inter_value=10,inter_value type=int int_value=10,int_value type=int
备注:结构体的反射基本和上代码一致不再举例
五:反射使用细节
①:reflect.Value.kind()返回的是常量;
②:Type和Kind的区别
Type是类别,Kind是类型,Type和Kind可能相同,可能不相同
相同如:var num int num的Type是int,num的Kind也是int
不同如:var struct1 Sturct1 struct1是结构体变量,这时Type是包.Struct1,Kind是struct
③:使用反射方式获取变量值且返回对应类型,要求数据类型匹配,比如x是int,则必须使用reflect。num := 10 + re_int_value.Int(),就是这类应用
④:通过反射修改变量
package main
import (
"fmt"
"reflect"
)
func reflectInt(i interface{}){
re_val := reflect.ValueOf(i)
fmt.Printf("re_val=%T
", re_val)
re_val.Elem().SetInt(20)
fmt.Printf("re_val=%v
", re_val)
}
func main() {
var number int = 10
reflectInt(&number)
fmt.Printf("number=%v
", number)
}
结果
[ `go run reflect.go` | done ]
re_val=reflect.Value
re_val=0xc00004e080
number=20
六:常量
①:与其他编程语言的区别
Go常量并不像其他编程语言,建议常量都是大写字母,但在Go中并没有这类建议;
当常量的名称首字母的大小写作用任然关系到访问的范围;
②:Go常量的声明
package main import ( "fmt" ) func main() { //常量声明的同时必须赋值 //const i int =10 const ( a = iota b c = 10 d e = iota ) fmt.Printf("a=%v,b=%v,c=%v,d=%v,e=%v", a, b, c, d, e) } 结果 a=0,b=1,c=10,d=10,e=4
以上是关于GO之反射的主要内容,如果未能解决你的问题,请参考以下文章