登录
首页 >  Golang >  Go问答

遇到问题:在反射中设置结构体的值

来源:stackoverflow

时间:2024-03-19 18:57:28 351浏览 收藏

在使用反射机制对结构体设置值时,开发者可能会遇到错误“panic: reflect: call of reflect.Value.SetString on struct Value”。这是因为代码试图直接对结构体的字段类型的值进行设置,而不是获取该字段的实际地址。

问题内容

假设我有一个基本结构,它是其他两个结构的组合:

type config struct {
    common.config
    common.serverconfig
    apipath      string `type:"string" name:"apipath" default:"localhost:8443" desc:"path to the grpc api server"`
    servepath    string `type:"string" name:"servepath" default:"/" desc:"path to serve the api from"`
    organization string `type:"string" name:"organization" default:"" desc:"default organization name"`
}

我想迭代结构中的每个字段并将值拉入结构中:

func newconfig(c configer) {
    setconfigflags(reflect.typeof(c).elem(), c.getviper())
}

所以我会这样称呼它:

conf := config{}
common.newconfig(&conf)

我的 setconfigflags 正在执行一些递归:

func setconfigflags(t reflect.type, viper *viper.viper) {
    for i := 0; i < t.numfield(); i++ {
        field := t.field(i)
        switch field.type.kind() {
        case reflect.struct:
            setconfigflags(field.type, viper)
            continue
        case reflect.string:
            fieldvalue := reflect.valueof(&field).elem()
            if !fieldvalue.isvalid() || !fieldvalue.canset() {
                return
            }
            fieldvalue.setstring(
                viper.getstring(field.tag.get("name")),
            )
        }
    }
}

现在,一旦我点击底部的 setstring 行,我就会收到此错误:

panic: reflect: call of reflect.Value.SetString on struct Value

当我查看 fieldvalue 的类型时,它是一个 structfield。我在尝试解决该值并更改该字段的值时遇到问题。我相信我没有正确获取实际结构字段的地址。这些示例和文档肯定没有帮助。

在这个特定的示例中,我正在提取 viper 值。基本上寻找一种通过结构标签定义我的 viper 定义的方法,这是最终目标。


解决方案


正如 mkopriva 的评论所指出的,代码正在尝试设置类型的值。使用一个值。

func setconfigflags(v reflect.value, viper *viper.viper) {
    t := v.type()
    for i := 0; i < t.numfield(); i++ {
        field := t.field(i)
        switch field.type.kind() {
        case reflect.struct:
            setconfigflags(v.field(i), viper)
            continue
        case reflect.string:
            v.field(i).setstring(viper.getstring(field.tag.get("name")))
        }
    }
}

这样称呼它:

func NewConfig(c Configer) {
    setConfigFlags(reflect.Value(c).Elem(), c.GetViper())
}

今天关于《遇到问题:在反射中设置结构体的值》的内容就介绍到这里了,是不是学起来一目了然!想要了解更多关于的内容请关注golang学习网公众号!

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