Golang reflect反射如何使用

这篇文章主要介绍“Golang reflect反射如何使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang reflect反射如何使用”文章能帮助大家解决问题。

    首先有一段以下结构体的定义

    type User struct {
    	UserName string
    	UserId   int `name:"uid"`
    }

    初始化一个结构体的实例

    u := User{"octoboy", 101}

    获取字段名

    首先获取变量的Type变量

    t := reflect.TypeOf(u)

    需要注意的是,如果传入的u是个指针,比如&User{"octoboy", 101}

    if t.Kind() == reflect.Ptr {
    	t = t.Elem()
    }

    这里通过Kind()函数获取变量的类型,判断如果类型为指针 需要使用Elem()获取指针指向的内容。

    然后遍历结构体的字段,获取其字段名称

    for i := 0; i < t.NumField(); i++ {
    		fmt.Println(t.Field(i).Name)
    	}

    输出结果:

    UserName

    UserId

    获取字段类型和值

    v := reflect.ValueOf(u)
    if v.Kind() == reflect.Ptr { //类型为指针 需要取elem
    	v = v.Elem()
    }

    获取字段的值或者赋值,需要用到ValueOf方法

    for i := 0; i < v.NumField(); i++ {
    	//v.Field(i).Int() v.Field(i).String() 都可以把值返回出来,相当于断言 类型不匹配会直接panic
    	//直接断成interface 任意类型
    	fmt.Println(v.Field(i).Interface())
    }

    输出结果:

    zyg

    101

    继续输出成员变量的类型

    for i := 0; i < v.NumField(); i++ {
    	fmt.Println(v.Field(i).Kind())
    }

    输出结果:

    string

    int

    设置字段值

    静态赋值

    //设置字段值
    	va := reflect.ValueOf(&u) //这里必须使用指针 否则后面调用Set无法使用无地址的值
    	if va.Kind() == reflect.Ptr { //类型为指针 需要取elem 意为取它指向的内容值
    		va = va.Elem()
    	for i := 0; i < va.NumField(); i++ {
    		//两种方法取设置字段的值,第二种更为统一
    		if va.Field(i).Kind() == reflect.String {
    			//重要 如果需要使用set取修改u中的值,需要在ValueOf中传入u的地址。否则会因为SetString使用了一个不能被寻址的值而造成panic
    			va.Field(i).SetString("octoboy")
    		}
    		if va.Field(i).Kind() == reflect.Int {
    			va.Field(i).Set(reflect.ValueOf(123))
    		}
    	}

    interface切片映射成结构体(动态赋值)

    //练手
    	values := []interface{}{"octoboy", 123}
    	for i := 0; i < va.NumField(); i++ {
    		if reflect.ValueOf(values[i]).Kind() == va.Field(i).Kind() {
    			va.Field(i).Set(reflect.ValueOf(values[i]))
    		}
    	}

    打印以上两种结构题变量

    输出结果:

    &{octoboy 123}

    进阶&mdash;map映射成结构体

    有如下代码

    //练习 把map映射成struct
    	set := map[string]interface{}{
    		"UserName": "zyg",
    		"UserId":   101,
    		"Age":      19,
    		"Sex":      1,
    	}
    	user := &User{}
    	MapToStruct(set, user)
    	fmt.Println(user)

    要求将map映射到user结构题中,即如果User的字段名如存在于map的key中,则将对应的value值赋给user结构题的成员变量

    有如下实现

    //str类型为interface{} 代表可以传入任意的结构体
    func MapToStruct(m map[string]interface{}, str interface{}) {
    	val := reflect.ValueOf(str)
    	if val.Kind() != reflect.Ptr {//必须是指针 否则无法用Set赋值
    		panic(any("must be ptr!"))
    	}
    	val = val.Elem()
    	if val.Kind() != reflect.Struct { //指针指向的必须是结构体
    		panic(any("must be struct"))
    	}
    	for i := 0; i < val.NumField(); i++ {
    		name := val.Type().Field(i).Name //value转type后取字段名称
    		if v, ok := m[name]; ok {        //如果根据tag做映射,就使用val.Type().Field(i).Tag.Get("name")作为key
    			if reflect.ValueOf(v).Kind() == val.Field(i).Kind() {
    				val.Field(i).Set(reflect.ValueOf(v))
    			}
    		}
    	}
    }

    关于“Golang reflect反射如何使用”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注蜗牛博客行业资讯频道,小编每天都会为大家更新不同的知识点。

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:niceseo99@gmail.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    评论

    有免费节点资源,我们会通知你!加入纸飞机订阅群

    ×
    天气预报查看日历分享网页手机扫码留言评论Telegram