Go语言(十五) 反射
时间:2022-07-25
本文章向大家介绍Go语言(十五) 反射,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
反射
变量介绍
- 变量的内在机制
- 类型信息,这部分是元信息,是预先定义好的
- 值类型,这部分是在程序运行过程中动态改变的
反射介绍
- 反射与空接口
- 空接口可以存储任何类型的变量
- 在程序运行时动态获取变量的类型信息和值信息,就叫
反射
import (
"fmt"
"reflect"
)
func TestType(a interface{}) {
//获取类型(静态信息)
t := reflect.TypeOf(a)
kind := t.Kind()
switch kind {
case reflect.Int:
fmt.Printf("a is a intn")
a = 2
case reflect.String:
fmt.Printf("a is a stringn")
}
fmt.Printf("t=%v,kind=%vnn",t,kind)
}
func TestValue(a interface{}) {
v := reflect.ValueOf(a)
//kind := v.Kind()
t := v.Type()
switch t.Kind() {
case reflect.Int:
fmt.Printf("a is a intn")
v.SetInt(10000)
case reflect.String:
v.SetString("xxx")
fmt.Printf("a is a stringn")
case reflect.Ptr:
t1 := v.Elem().Type()
switch (t1.Kind()) {
case reflect.Int:
v.Elem().SetInt(100)
fmt.Printf("ptn is int n")
case reflect.String:
v.Elem().SetString("hello")
fmt.Printf("ptn is stringn")
}
fmt.Printf("a=%v is a point typen",t1)
}
fmt.Printf("v=%v,kind=%vnn",v,t)
}
func main() {
//var a int
//TestType(a)
//fmt.Printf("a=%vn",a)
//var b string
//TestType(b)
var c int
TestValue(&c)
var d string
TestValue(&d)
fmt.Printf("c=%v, d=%vn",c,d)
}
结构体反射
type Users struct {
Name string `json:"name"`
Age int
Sex string
}
//1. 获取a的类型
//2. 我要动态改变a里面存的值
//3. 如果a里面存储的是一个结构体,那可以通过反射获取结构体中的字段信息以及调用结构体里面的方法
func TestValueStruct(a interface{}) {
v := reflect.ValueOf(a)
t := v.Type()
switch t.Kind() {
case reflect.Struct:
fieldNum := t.NumField()
fmt.Printf("field num:%dn", fieldNum)
for i := 0; i <fieldNum; i++{
field := t.Field(i)
vField := v.Field(i)
fmt.Printf("field[%d] name:%s, json key:%s, val:%vn",
i, field.Name, field.Tag.Get("json"), vField.Interface())
}
}
}
func main() {
var user Users
user.Name = "xxx"
user.Age = 100
user.Sex = "man"
TestValueStruct(user)
fmt.Printf("user:%#vn", user)
}
调用结构体中的方法
type S struct {
A int
B string
}
func (s *S) Test() {
fmt.Printf("this is a testn")
}
func (s *S) SetA (a int) {
s.A = a
}
func main() {
s := S{23,"abc"}
v := reflect.ValueOf(&s)
m := v.MethodByName("Test")
var args1 []reflect.Value
m.Call(args1)
setA := v.MethodByName("SetA")
var args2 []reflect.Value
args2 = append(args2,reflect.ValueOf(100))
setA.Call(args2) #修改结构体中的值
fmt.Printf("s:%#vn",s)
}
反射总结以及应用场景
- 总结:
- 在运行时动态的获取一个变量的类型信息(typeOf)和值信息(valueOf)
- 应用场景
- 各种数据库的ORM
- 配置文件相关的库,比如yaml,ini等
- 序列化和反序列化,比如json,protoBuf等数据协议
- 各种数据库的ORM
json序列化简版代码
package json_reflect
import (
"fmt"
"reflect"
)
func Marshals(data interface{}) (jsonStr string) {
t := reflect.TypeOf(data)
v := reflect.ValueOf(data)
switch t.Kind(){
case reflect.String,reflect.Int,reflect.Int32:
jsonStr = fmt.Sprintf(""%v"", data)
case reflect.Struct:
numField := t.NumField()
for i := 0; i < numField; i++ {
//类型信息
name := t.Field(i).Name
tag := t.Field(i).Tag.Get("json")
if len(tag) > 0 {
name = tag
}
//值信息
vField := v.Field(i)
vFieldValue := vField.Interface()
//拼接json
if t.Field(i).Type.Kind() == reflect.String {
jsonStr += fmt.Sprintf(""%s":"%v"", name, vFieldValue)
} else {
jsonStr += fmt.Sprintf(""%s":%v", name, vFieldValue)
}
if i != numField - 1 {
jsonStr += ","
}
}
jsonStr = "{" +jsonStr + "}"
}
return
}
测试代码
package main
import (
"fmt"
"oldBoy/day9/json_reflect"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Sex string `json:"sex"`
}
func main() {
var a string = "hello abc"
jsonStr := json_reflect.Marshals(a)
fmt.Printf(jsonStr)
var user User
user.Name = "aaa"
user.Age = 10
user.Sex = "male"
jsonStr = json_reflect.Marshals(user)
fmt.Printf(jsonStr)
}
- 无人值守,检测程序正常运行,遇故障则重启服务
- JS魔法堂:jsDeferred源码剖析
- JavaSE(八)之集合概述
- 浅谈PHP开发与Java开发的优劣势,还不知道学习方向的可以来看看
- KVM+Qemu+Libvirt实战
- 内核级虚拟化技术
- tomcat配置ROOT目录和多站点
- IntelliJ IDEA使用(一)基本设置与类、方法模板设置
- JS魔法堂:从void 0 === undefined说起
- Maven(三)在Eclipse中使用Maven与Maven坐标
- Nginx多站点设置及负载均衡
- Maven(二)Maven项目的创建(命令、myeclipse)及生命周期
- JS魔法堂:初探传说中的setImmediate函数
- 配置nginx.conf实现负载均衡
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Day12.魔法方法&方法重写
- Linux基础第一课——基础知识了解
- 【Vue CLI】手把手教你撸插件
- Linux基础第二课——系统架构
- Day13.继承&多态
- Linux第三课——目录操作
- Linux基础第四课——文件操作
- Linux基础第五课——用户管理
- Linux基础第六课——grep|awk|sort|uniq
- Python向上取整,向下取整以及四舍五入函数
- 使用requests模块post payload请求
- 解决HTTP status code is not handled or not allowed
- Day8.函数那些事儿
- mac下更改Jupyter notebook工作目录
- Scrapy中将item字段转为简体or繁体