登录
首页 >  Golang >  Go问答

使用反射在Golang中更新地图的值

来源:stackoverflow

时间:2024-02-24 21:15:25 464浏览 收藏

知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个Golang开发实战,手把手教大家学习《使用反射在Golang中更新地图的值》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!

问题内容

我遇到了一个问题,我希望制作一个通用的方法来更新地图中的值,如下例:

我主要想做的,提供一个通用的方法

  1. 读取配置;
  2. 验证配置是否有效
  3. 将配置反序列化为指定对象
type configkey string

var studentkey configkey
var teacherkey configkey

type teacher struct {
    age int `json:"age"`
}

func testreflect(t *testing.t) {
    // update student
    student := make(map[int]student)
    update(studentkey, &student, func(value interface{}) bool {
        if m, ok := value.(map[int]student); ok && m[0].name == "test" {
            return true
        }
        return false
    })
    fmt.println("outer:", student)
    // update teacher
    teacher := make(map[int]teacher)
    update(teacherkey, &teacher, func(value interface{}) bool {
        if m, ok := value.(map[int]teacher); ok && m[0].age == 1 {
            return true
        }
        return false
    })
    fmt.println("outer:", teacher)
}

// func to auto update config, for make a general method
func update(key configkey, ori interface{}, validate func(value interface{}) bool) {
    valuestr := getconfigvalue(key)
    temp := copyinterface(ori)
    _ = json.unmarshal([]byte(valuestr), &temp)
    if !validate(valuestr) {
        return
    }
    fmt.println("inner:", temp)
    ori = temp
}

func getconfigvalue(key configkey) string {
    switch key {
    case studentkey:
        return `{"0":{"name":"test"}}`
    case teacherkey:
        return `{"0":{"age":1}}`
    }
    return ""
}

func copyinterface(a interface{}) interface{} {
    return reflect.new(reflect.typeof(a).elem())
}

预期输出结果为:

inner: map[0:map[name:test]]
outer: map[0:map[name:test]]
inner: map[0:map[age:1]]
outer: map[0:map[age:1]]

但实际输出是:

outer: map[]
outer: map[]

如何才能达到预期的输出?


正确答案


这是更正后的更新函数,其中包含描述该函数如何工作的注释。

func update(key ConfigKey, ptarget interface{}, validate func(interface{}) bool) {
    valueStr := getConfigValue(key)

    // Get target value. Target is expected to be a pointer to
    // a value. Elem() dereferences the pointer.
    target := reflect.ValueOf(ptarget).Elem()

    // Create a new empty value. New returns a pointer. Elem()
    // dereferences the pointer.
    scratch := reflect.New(target.Type()).Elem()

    // Unmarshal to the scratch value.
    err := json.Unmarshal([]byte(valueStr), scratch.Addr().Interface())
    if err != nil {
        return
    }

    // Call the validation function.
    if !validate(scratch.Interface()) {
        return
    }

    // Assign the scratch value to the target value.
    target.Set(scratch)
}

Run the test on the Go Playground

今天关于《使用反射在Golang中更新地图的值》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>