怎么查网站是否被k,网页制作设计步骤,企业工商信息公示系统,电子类网站建设反射 文章目录 反射1、反射的使用场景1#xff09;结构体标签的应用2#xff09;使用反射机制编写函数的适配器#xff08;桥连接#xff09; 2、反射的基本介绍-1.基本介绍-2.反射的图解-3.反射重要的函数和概念 3.反射快速入门-1.请编写一个函数#xff0c;演示对#…反射 文章目录 反射1、反射的使用场景1结构体标签的应用2使用反射机制编写函数的适配器桥连接 2、反射的基本介绍-1.基本介绍-2.反射的图解-3.反射重要的函数和概念 3.反射快速入门-1.请编写一个函数演示对基本数据类型、interface{}、reflect.Value进行反射的基本操作。-2.请编写一个案例演示对结构体类型、interface{}、reflect.Value进行反射的基本操作 4.反射的注意事项和细节说明1reflect.Value.Kind获取变量的类别返回的是一个常量2Type是类型kind是类别Type和Kind可能是相同的也可能是不同的 5.反射练习题6.反射的最佳实践 1、反射的使用场景
1结构体标签的应用 2使用反射机制编写函数的适配器桥连接 2、反射的基本介绍
-1.基本介绍
1反射可以在运行时动态获取变量的各种信息比如变量的类型type类别(kind)
2如果是结构体变量还可以获取到结构体本身的信息包括结构体的字段、方法
3通过反射可以修改变量的值可以调用关联的方法
4使用反射需要import (“reflect”)
-2.反射的图解 -3.反射重要的函数和概念
1reflect.TypeOf(变量名)。获取变量的类型返回reflect.Type类型
2reflect.ValueOf(变量名)。获取变量的值返回reflect.Value类型reflect.Value是一个结构体类型。通过reflect.Value.可以获取到关于该变量的很多信息
3变量、interface{}和reflect.Value是可以相互转换的这点在实际开发中会经常使用到。
3.反射快速入门
-1.请编写一个函数演示对基本数据类型、interface{}、reflect.Value进行反射的基本操作。
代码演示
package mainimport (fmtreflect)//专门反射演示func reflectTest01(b interface{}) {//通过反射获取的传入的变量 type,kind,值//1.先获取到reflect.TyperTyp :reflect.TypeOf(b)fmt.Println(rTyp,rTyp) //int//2.获取到reflectValuerVal :reflect.ValueOf(b) //100// n1 : 10// n2 : 2 rVal// fmt.Println(n2,n2)//erro // n1 : 10n2 : 2 rVal.Int()fmt.Println(n2,n2) //102fmt.Printf(rVal%v type%T\n,rVal,rVal) //rVal100 typereflect.Value//下面我们将rVal转成interface{}iv : rVal.Interface()//将interface{}通过断言转成需要的类型num2 : iv.(int)fmt.Println(num2,num2) //num2 100}func main() {//-1.请编写一个函数演示对基本数据类型、interface{}、reflect.Value进行反射的基本操作。//1、先定义一个intvar num int 100reflectTest01(num)}-2.请编写一个案例演示对结构体类型、interface{}、reflect.Value进行反射的基本操作 //专门演示对结构体的反射func reflectTest02(b interface{}) {//通过反射获取的传入的变量 type,kind,值//1.先获取到reflect.TyperTyp :reflect.TypeOf(b)fmt.Println(rTyp,rTyp) //rTyp main.Student//2.获取到reflectValuerVal :reflect.ValueOf(b)//下面我们将rVal转成interface{}iv : rVal.Interface()fmt.Printf(iv%v ,iv type%T\n,iv,iv) //iv{Tom 20} ,iv typemain.Student//将interface{}通过断言转成需要的类型// fmt.Printf(iv%v ,iv type%T name\n,iv,iv,iv.Name) //erro无法取出name的值//所以先要进行断言stu,ok :iv.(Student)if ok {fmt.Printf(stu.Name%v\n,stu.Name)//stu.NameTom}}type Student struct {Name stringAge int}func main() {//2.定义一个Student的实例stu : Student{Name : Tom,Age : 20,}reflectTest02(stu)}4.反射的注意事项和细节说明
1reflect.Value.Kind获取变量的类别返回的是一个常量
补充常量是知识
常量介绍 常量使用const修改 常量在定义的时候必须初始化 常量不能修改 常量只能修饰bool、数值类型(int,float系列)、string类型 语法 const identifier [type] value package main
import (fmt
)
func main() {var num intnum 90 //常量声明的时候必须赋值const tax int 90// tax 10 //常量是不能修改的fmt.Println(num,tax)//常量只能修饰bool、数值类型(int,float系列)、string类型//const b num /3 erro
}常量使用注意事项 1》比较简洁的写法 func main () {
const(a 1b 2
)
}2》还有一种专业的写法 func main(){const(a iotabc)fmt.Println(a,b,c)//0,1,2
}3》Golang中没有常量名必须大写的规范 4》仍然通过首字母的大小来控制常量的访问范围
2Type是类型kind是类别Type和Kind可能是相同的也可能是不同的
比如: var num int 10 num 的Type是int, Kind也是int
比如var stu Student stu 的Type是包名.Student,Kind是structKind的等级 Type的等级
3通过反射可以让变量在interface{}和Reflect.Value之间相互转换
4使用反射的方式来获取变量的值并返回对应的类型要求数据类型匹配比如x是int,那么就应该使用reflect.Value(x)Int(),而不能使用其他的否则报panic
5通过反射的值来修改变量。注意当使用SetXxx方法来设置需要通过对应的指针类型来完成这样才能改变传入的值同时需要使用到reflect.Value.Elem()方法
package main
import (fmtreflect
)//通过反射修改
//num int 的值
//修改student的值func reflect01(b interface{}){//获取到reflect.ValuerVal : reflect.ValueOf(b)rVal.Elem().SetInt(20)
}
func main() {var num int 10reflect01(num)fmt.Println(num,num) //20//你可以这样理解这句话rVal.Elem()// num : 9// ptr *int num// num2 :*ptr
}6如何理解rVal.Elem()
//你可以这样理解这句话rVal.Elem()// num : 9// ptr *int num// num2 :*ptr
}5.反射练习题
1给你一个变量 var v float64 1.2.请使用反射来得到它的reflect.Value,然后获取对应的Type,Kind和值并将reflect.Value转换成interface{}.,再将interface{}转换成float64
package mainimport (fmtreflect)func reflect01(b interface{}) {num : reflect.ValueOf(b)kind1 :num.Kind()iv :num.Interface()fmt.Printf(b的reflect.Value是%v,kind值为%v,num转换为interface的值为%v,num,kind1,iv)}func main() {var n float64 65.9reflect01(n)}2给字符串改名题 var str string tomfs :reflect.ValueOf(str) //这里要改成地址fs.Elem().SetString(jackma)fmt.Println(str)6.反射的最佳实践
1使用反射来遍历结构体的字段调用结构体的方法并获取结构体标签的值 2使用反射的方式来获取结构体的tag标签,遍历字段的值修改字段值调用结构体方法 val.Method(0).Call() 调用第一个方法 方法的排序默认是按照函数名的排序(ASCII码) 定义了两个函数testl 和test2 定义一个适配器函数用作统一 处理接口 使用反射操作任意结构体类型 使用反射创建并操作结构体
package main
import (fmtreflect
)//定义了一个Monster结构体
type Monster struct{Name string json:nameAge int json:ageScore float32 json:成绩Sex string
}// 方法: 返回两数之和
func(s Monster) GetSum(n1, n2 int) int{return n1 n2
}// 方法: 接收四个值, 给S赋值
func(s Monster) Set(name string, age int, score float32, sex string){s.Name names.Age ages.Score scores.Sex sex
}//方法显示s的值
func (s Monster) Print() {fmt.Println(--start--)fmt.Println(s)fmt.Println(--end--)
}func TestStruct(a interface{}){//获取reflect.Type类型typ : reflect.TypeOf(a)//获取reflect.Value类型val : reflect.ValueOf(a)//获取到a对应的类别kd : val.Kind()//如果传入的不是struct,就退出if kd ! reflect.Struct {fmt.Println(Expect struct)return}//获取到该结构体有几个字段num : val.NumField()fmt.Printf(struct has %d fields\n, num) //4//变量结构体的所有字段for i : 0; i num; i {fmt.Printf(Field %d:值为%v\n, i, val.Field(i))//获取到struct 标签,注意需要通过reflect.Type来获取tag标签的值tagVal : typ.Field(i).Tag.Get(json)//如果该字段于tag标签就显示否则就不显示if tagVal ! {fmt.Printf(Field %d: tag为%v\n, i, tagVal)}}//获取到该结构体有多少个方法numOfMethod : val.NumMethod()fmt.Printf(struct has %d methods\n, numOfMethod)//var params []reflect.Value//方法的排序默认是按照函数名的排序(ASCII码)val.Method(1).Call(nil)//获取到第二个方法。调用它//调用结构体的第1个方法Method(0)var params []reflect.Value //声明了[]reflect.Valueparams append(params, reflect.ValueOf(10))params append(params, reflect.ValueOf(40))res : val.Method(0).Call(params) //传入的参数是[]reflect.Value,返回[]reflect.Valuefmt.Println(res, res[0].Int()) //返回结果,返回的结果是[]reflect.Value*/
}func main(){var a Monster Monster{Name: 黄鼠狼精,Age: 400,Score: 30.8,} //将Monster实例传递给TestStruct函数TestStruct(a)
}
2使用反射操作任意结构体类型
type user struct {UserId stringName string}func TestReflectStruct(t *testing.T){var {model *usersv reflect.Value}model user{}sv reflect.ValueOf(model)t.Log(reflect.ValueOf,sv.kind().String())svsv.Elem()t.Log(reflect.ValueOf,,sv.kind().String())sv.FieldByName(userId).SetString(12345678)sv.FieldByName(Name).SetString(nickname)t.Log(model,model)}