import (
"fmt"
"reflect"
)
type User struct {
Name string
age int
}
type Student struct {
Name string `json:"Name" feifei:"Name_xxx"`
age StudentAge
}
type StudentAge struct {
Name string
age int
}
func main() {
user := User{
Name: "我是User",
age: 4,
}
studentage := StudentAge{
Name: "我是StudentAge",
age: 5,
}
student := Student{
Name: "我是Student",
age: studentage,
}
DuanYan(student, user)
FanShe(&student, user)
fmt.Println(student)
}
// 断言是什么,断言是声明这个变量他是什么,有时候系统不知道变量是什么,就需要你断言
// 将数据放入interface{}后需要断言才能使用,不然系统不知道他是什么,可以配合用v.(type)知道v的类型,也可以用v.(结构体)直接断言
// 如果断言失败则会返回错误信息errs,ok := err.(validator.ValidationErrors),ok就是错误信息
func DuanYan(v interface{}, o any) {
//判断结构体的类型
switch v.(type) {
case User:
fmt.Println(v.(User).Name)
case Student:
fmt.Println(v.(Student).Name)
}
//反射是什么,断言的变量修改起来会很麻烦。反射可以知道进来的数据他的原始数据类型并可以进行操作
//反射的优点是可以动态修改数据值
//缺点是性能不好,可读性不好
//TypeOf可以直接知道他是什么类型 结果为 main.User
t := reflect.TypeOf(v)
fmt.Println("我的类型是:", t)
//TypeOf可以直接得到他结构体里的值 结果为 {我是User 4}
y := reflect.ValueOf(v)
fmt.Println("我的所有的值是:", y)
//t.NumField()结构体的总数量,y.Field(i)结构体对应的索引
for i := 0; i < t.NumField(); i++ {
fmt.Println(
"获取字段名:", t.Field(i).Name,
"\r\n获取json内容:", t.Field(i).Tag.Get("feifei"),
"\r\n获取字段对应内容:", y.Field(i),
"\r\n获取字段类型:", t.Field(i).Type,
)
}
//根据索引去找内容
fmt.Println(y.Field(0))
fmt.Println(y.Field(1))
//根据索引去找结构体内容,[]int{0}可以根据多层层级结构体找数据
fmt.Println(y.FieldByIndex([]int{0}))
fmt.Println(y.FieldByIndex([]int{1}))
fmt.Println(y.FieldByIndex([]int{1, 0}))
//根据名称去找结构体内容
fmt.Println(y.FieldByName("Name"))
//Kind是获取这个接口的底层类型
ty := t.Kind()
if ty == reflect.Struct {
fmt.Println("我是Struct")
} else if ty == reflect.Int {
fmt.Println("我是Int")
} else if ty == reflect.String {
fmt.Println("我是String")
}
}
func FanShe(v interface{}, o interface{}) {
y := reflect.ValueOf(v)
//Elem就是变量的原始类型
p := y.Elem()
fmt.Println(y, p)
//根据Name找到字段并修改结构体的值,注意字段首字母必须大写!!否则不能被导出
p.FieldByName("Name").SetString("啊对对对")
}