go使用reflect包修改结构体的值

臭大佬 2022-11-22 10:09:29 165
Go 
简介 go使用reflect包修改结构体的值

问题

有个方法是通用的,参数是Interface,可以丢进来任何结构体,这时候,就不知道 interface 里面有哪些成员了,假设我们知道 interface 里面有 ShopId 字段,并且我们要修改它的值,该怎么操作呢?

方法

直接上代码

package test

import (
    "reflect"
    "testing"
)

func TestA(t *testing.T) {
    type shop struct {
        ShopId int64
        Name   string
    }
    d := &shop{
        ShopId: 2,
        Name:   "测试一下",
    }
    var e int64 = 40
    changeValue(d, e)
    t.Log(d)
}

// changeValue 修改 s 的 shopId 的值
func changeValue(s interface{}, value int64) {
    // 使用ValueOf()获取到变量的Value对象
    ref := reflect.ValueOf(s)
    // value是一个指针,这里获取了该指针指向的值,相当于value.Elem()
    ref = reflect.Indirect(ref)
    // 如果是结构体,才往下走
    if ref.Kind() != reflect.Struct {
        return
    }
    //获取结构体shop中的ShopId字段的值
    val := ref.FieldByName("ShopId")
    // 要先判断是否有这个值,如果类型为 reflect.Invalid,则不存在这个成员
    // val.Kind() 获取对象或者变量的类型, 如果类型不为 Invalid ,则赋值
    if val.Kind() == reflect.Int64 {
        // ShopId 的值设为 value
        val.SetInt(value)
    }
}

结果
=== RUN TestA
a_test.go: 19: &{40 测试一下}
—- PASS: TestA (0.00s)
PASS

如果不存在要修改的成员名会不会出问题呢?我们把结构体的 ShopId 改成 ShopIds 看一下结果:

package test

import (
    "reflect"
    "testing"
)

func TestA(t *testing.T) {
    type shop struct {
        ShopIds int64
        Name    string
    }
    d := &shop{
        ShopIds: 2,
        Name:    "测试一下",
    }
    var e int64 = 40
    changeValue(d, e)
    t.Log(d)
}

// changeValue 修改 s 的 shopId 的值
func changeValue(s interface{}, value int64) {
    // 使用ValueOf()获取到变量的Value对象
    ref := reflect.ValueOf(s)
    // value是一个指针,这里获取了该指针指向的值,相当于value.Elem()
    ref = reflect.Indirect(ref)
    //获取结构体shop中的ShopId字段的值
    val := ref.FieldByName("ShopId")
    // 要先判断是否有这个值,如果类型为 reflect.Invalid,则不存在这个成员
    // val.Kind() 获取对象或者变量的类型, 如果类型不为 Invalid ,则赋值
    if val.Kind() != reflect.Invalid {
        // ShopId 的值设为 value
        val.SetInt(value)
    }
}

结果
=== RUN TestA
a_test.go: 19: &{2 测试一下}
—- PASS: TestA (0.00s)
PASS

并没有出来恐慌或者错误.