了解go的反射
- 反射:与 面向对象中的反射类似!
- 程序运行中,获取到的信息(变量:类型,值。 结构体:字段,方法)
- 可以通过反射机制,来改变变量和值
- reflect 包, 实现反射
- reflect.Type : 类型。 指示某一种类型
- reflect.Value : 值
- reflect.Kind : 种类。用于反射场景更多,指代的是相似的一些类型,当遇到自定义类型时,使用kind获取原始种类
- 为什么使用反射
- 编写函数时,不知道函数传递的参数是什么类型。使用any接收一切参数,利用反射 reflect 识别数据类型,种类
- 用户输入数据类型不清楚时,利用反射获取数据类型,种类。 程序运行期间动态处理
静态类型和动态类型
- 在反射过程中。程序编译的时候变量类型为静态类型,程序运行过程中变量是动态类型。
- 静态类型:
- 动态类型:
- var A interface {} // 静态类型
- A = 10 // interface 静态类型, 运行时属于动态类型 int
- A = "abcd" // interface 静态类型, 运行时属于动态类型 string
反射使用
package main
import (
"fmt"
"reflect"
)
type AType int
type User struct {
name string
age int
sex bool
custom AType
}
func (u User) Say(content string) {
fmt.Printf("用户:%s 。 说:%s\n", u.name, content)
}
func (u User) GetInfo() {
fmt.Printf("用户名:%s,用户年龄:%d,用户性别:%d", u.name, u.age, u.sex)
}
func analyticDataFunc(v interface{}) {
getType := reflect.TypeOf(v)
fmt.Println("v type:", getType)
vName := getType.Name()
fmt.Println("v name:", vName)
vKind := getType.Kind()
fmt.Println("v kind:", vKind)
getValue := reflect.ValueOf(v)
fmt.Println("v value:", getValue)
for index := 0; index < getValue.NumField(); index++ {
vFieldName := getType.Field(index)
vFieldValue1 := getValue.Field(index)
fmt.Println("v变量包含的信息:", "字段:", vFieldName, "值:", vFieldValue1)
}
for i := 0; i < getType.NumMethod(); i++ {
method := getType.Method(i)
fmt.Printf("method Name:【%s】 method Type:【%v】\n", method.Name, method.Type)
}
}
func main() {
var u = User{"张三", 3, true, 1000000}
fmt.Println("define u data:", u)
u.Say("你好")
u.GetInfo()
analyticDataFunc(u)
}
通过反射修改数据
package main
import (
"fmt"
"reflect"
)
func main() {
var num = 3.14
pointer := reflect.ValueOf(&num)
newValue := pointer.Elem()
fmt.Println("类型:", newValue.Type())
fmt.Println("判断该类型能否修改:", newValue.CanSet())
newValue.SetFloat(2.11)
fmt.Println("newValue:", newValue)
}
通过反射修改变量的函数
package main
import (
"fmt"
"reflect"
)
func reflectionModifiedVariableFunc(v any) reflect.Value {
pointer := reflect.ValueOf(v)
newValue := pointer.Elem()
newValueType := newValue.Kind()
fmt.Println(" [待修改变量] 值:", newValue)
fmt.Println(" [待修改变量] 原类型:", newValueType)
fmt.Println(" [待修改变量] 是否能修改:", newValue.CanSet())
if newValueType == reflect.Int {
newValue.SetInt(100)
}
if newValueType == reflect.String {
newValue.SetString("李四")
}
return newValue
}
func main() {
var modifyVal1 = 1
var modifyVal2 = "你好"
fmt.Println("【修改前】", modifyVal1, modifyVal2)
res1 := reflectionModifiedVariableFunc(&modifyVal1)
res2 := reflectionModifiedVariableFunc(&modifyVal2)
fmt.Println("【修改后】", res1, res2)
}
通过反射修改结构体
package main
import (
"fmt"
"reflect"
)
type Student struct {
Name string
age int
Age int
}
func main() {
var stu = Student{"张三", 19, 20}
fmt.Println("stu:", stu)
stuStructValue := reflect.ValueOf(&stu)
if stuStructValue.Kind() == reflect.Ptr {
newValue := stuStructValue.Elem()
if newValue.CanSet() {
newValue.FieldByName("Name").SetString("lisi")
newValue.FieldByName("Age").SetInt(333)
}
}
fmt.Println("反射修改后的stu:", stu)
}
反射调用结构体方法
- MethodByName 找到函数名。必须大写
- Call 执行 函数。
package main
import (
"fmt"
"reflect"
)
type StudentA struct {
Name string
Age int
}
func (s StudentA) Say(content string) {
fmt.Println(s.Name, "Say:【", content, "】")
}
func (s StudentA) GetInfo() {
fmt.Printf("name: %s, age: %d\n", s.Name, s.Age)
}
func main() {
var stu = StudentA{"张三", 20}
fmt.Println("stu:", stu)
stuStructValue := reflect.ValueOf(&stu)
fmt.Printf("stuStructValue Kind:%s, Type:%s\n", stuStructValue.Kind(), stuStructValue.Type())
if stuStructValue.Kind() == reflect.Ptr {
newValue := stuStructValue.Elem()
fmt.Printf("newValue Kind:%s, Type:%s\n", newValue.Kind(), newValue.Type())
newValue.MethodByName("GetInfo").Call(nil)
args := make([]reflect.Value, 1)
args[0] = reflect.ValueOf("这是反射调用")
newValue.MethodByName("Say").Call(args)
}
}
反射调用普通函数
package main
import (
"fmt"
"reflect"
)
func f1() {
fmt.Println("无参函数")
}
func f2(i string) {
fmt.Println("有参函数:", i)
}
func f3(i, s string) string {
fmt.Println("有参函数,有返回值:", i, s)
return s
}
func main() {
v1 := reflect.ValueOf(f1)
fmt.Println(v1.Kind(), v1.Type())
v1.Call(nil)
v2 := reflect.ValueOf(f2)
fmt.Println(v2.Kind(), v2.Type())
v2Args := make([]reflect.Value, 1)
v2Args[0] = reflect.ValueOf("你好")
v2.Call(v2Args)
v3 := reflect.ValueOf(f3)
fmt.Println(v3.Kind(), v3.Type())
v3Args := make([]reflect.Value, 2)
v3Args[0] = reflect.ValueOf("不好")
v3Args[1] = reflect.ValueOf("aaa")
v3.Call(v3Args)
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?