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

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

反射结构体

package main
import (
    "fmt"
    "reflect"
)
type Order struct {
    orderId string `json:"order_id"`
    price   int    `json:"price"`
}
func main() {
    type InfoData struct {
        ShopUuid string `json:"shopUuid"`
        UserUuid string `json:"userUuid"`
        Types    int64  `json:"types"`
        Status   int64  `json:"status"`
    }
    d := InfoData{
        "Sfx135", "sd54", 1, 2,
    }
    // 返回原始值的值信息
    v := reflect.ValueOf(d)
    if v.Kind() != reflect.Struct {
        return
    }
    // 获得结构体成员的详细信息
    f := reflect.TypeOf(d)
    for i := 0; i < f.NumField(); i++ {
        field := f.Field(i)
        // field.Name 可以获取key
        // v.Field(i).String() 获取对应的值
        switch field.Name {
        case "ShopUuid":
            fmt.Printf("key:%s val:%s type: %v\n", field.Name, v.Field(i).String(), field.Type)
        case "UserUuid":
            fmt.Printf("key:%s val:%s type: %v\n", field.Name, v.Field(i).String(), field.Type)
        case "Status":
            fmt.Printf("key:%s val:%d type: %v\n", field.Name, v.Field(i).Int(), field.Type)
        }
    }
    // 取字段
    vv := reflect.ValueOf(&d)
    vv = vv.Elem()
    vf := vv.FieldByName("ShopUuid")
    if vf.Kind() == reflect.String {
        // 原值
        fmt.Printf("原值:%v\n", vf.String())
        // 修改值
        vf.SetString("SW56")
        fmt.Printf("新值:%v\n", vf.String())
    }
    fmt.Print(d)
}

结果:
key:ShopUuid val:Sfx135 type: string
key:UserUuid val:sd54 type: string
key:Status val:2 type: int64
原值:Sfx135
新值:SW56
{SW56 sd54 1 2}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Galloping-Vijay

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值