草庐IT

dictionary - Go中通过反射为struct成员赋值

coder 2023-07-01 原文

我有一个包含成员 A、B、C 字符串的结构体 v。使用反射,我可以获得字段的名称及其值:

typ := v.Type()
for i := 0; i < v.NumField(); i++ {
    // gets us a StructField
    fi := typ.Field(i)
    fieldname := fi.Name
    fmt.Println(fieldname)
    val := fmt.Sprintf("%v", v.Field(i).Interface())
 }

既然我有了名字,并且可以得到值OUT,我可以给字段赋新值吗?我基本上想做的是:

v.Field(fieldname).Interface() = "new value"

但这显然行不通。如果您只知道字段的名称,是否可以将值分配给结构?

在实践中,我试图将 map[string]string 中的值分配给结构中的相应字段,其中结构和映射定义可能会随着时间的推移而扩展变化,而映射可能包含比结构更多或更少的值。我考虑过使用 JSON 来实现它,但这种方法让我有点感冒,因为使用反射“几乎”到达那里是多么容易!

谢谢, 肯

最佳答案

是的,这是可能的。

简介

由于要访问和修改变量(或字段)的值,因此需要使用 reflect.Value 输入而不是 reflect.Type .您可以通过 reflect.ValueOf() 获取它.同样为了用反射修改它,你需要传递 struct 的地址(指针)。或您要修改的值(否则您只能读取它而不能修改它)。

但是您不想修改地址/指针,而是修改指向 的值,因此您必须从Value 中“导航”指向 Value 的指针指向变量(结构)的,这就是 Value.Elem() 是为了。它看起来像这样:reflect.ValueOf(&s).Elem()

您可以获得Value具有 Value.FieldByName() 的结构字段方法,因为我们将指针的地址传递给了 ValueOf()函数将可设置

代码

看懂后代码比介绍简单多了。您也可以在 Go Playground 上试用:

var s struct {
    A, B, C string
}
s.A, s.B, s.C = "a1", "b2", "c3"

fmt.Println("Before:  ", s)

v := reflect.ValueOf(&s).Elem()

v.FieldByName("A").SetString("2a")
v.FieldByName("B").SetString("2b")
v.FieldByName("C").SetString("2c")

fmt.Println("After:   ", s)

// Using a map:
m := map[string]string{"A": "ma", "B": "mb", "C": "mc"}
for mk, mv := range m {
    v.FieldByName(mk).SetString(mv)
}

fmt.Println("From Map:", s)

输出:

Before:   {a1 b2 c3}
After:    {2a 2b 2c}
From Map: {ma mb mc}

我建议阅读这篇博文以了解 Go 中反射的基础知识:

The Laws of Reflection

关于dictionary - Go中通过反射为struct成员赋值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28115815/

有关dictionary - Go中通过反射为struct成员赋值的更多相关文章

  1. ruby-on-rails - Rails 模型——非持久类成员或属性? - 2

    对于Rails模型,是否可以/建议让一个类的成员不持久保存到数据库中?我想将用户最后选择的类型存储在session变量中。由于我无法从我的模型中设置session变量,我想将值存储在一个“虚拟”类成员中,该成员只是将值传递回Controller。你能有这样的类(class)成员吗? 最佳答案 将非持久属性添加到Rails模型就像任何其他Ruby类一样:classUser扩展解释:在Ruby中,所有实例变量都是私有(private)的,不需要在赋值前定义。attr_accessor创建一个setter和getter方法:classUs

  2. ruby - 带括号和 splat 运算符的并行赋值 - 2

    我明白了:x,(y,z)=1,*[2,3]x#=>1y#=>2z#=>nil我想知道为什么z的值为nil。 最佳答案 x,(y,z)=1,*[2,3]右侧的splat*是内联扩展的,所以它等同于:x,(y,z)=1,2,3左边带括号的列表被视为嵌套赋值,所以它等价于:x=1y,z=23被丢弃,而z被分配给nil。 关于ruby-带括号和splat运算符的并行赋值,我们在StackOverflow上找到一个类似的问题: https://stackoverflow

  3. ruby - 变量赋值后的 if 语句 - 有多常见? - 2

    我最近与一位同事讨论了以下Ruby语法:value=ifa==0"foo"elsifa>42"bar"else"fizz"end我个人并没有看到太多这种逻辑,但我的同事指出,这实际上是一种相当普遍的Rubyism。我试着用谷歌搜索这个主题,但没有找到任何文章、页面或SO问题来讨论它,这让我相信这可能是一种非常实际的技术。然而,另一位同事发现语法令人困惑,而是将上面的逻辑写成这样:ifa==0value="foo"elsifa>42value="bar"elsevalue="fizz"end缺点是value=的重复声明和隐式elsenil的丢失,如果我们想使用它的话。这也感觉它与Ruby

  4. ruby-on-rails - rspec 模拟对象属性赋值 - 2

    我有一个rspec模拟对象,一个值赋给了属性。我正在努力在我的rspec测试中满足这种期望。只是想知道语法是什么?代码:defcreate@new_campaign=AdCampaign.new(params[:new_campaign])@new_campaign.creationDate="#{Time.now.year}/#{Time.now.mon}/#{Time.now.day}"if@new_campaign.saveflash[:status]="Success"elseflash[:status]="Failed"endend测试it"shouldabletocreat

  5. ruby - 重构条件变量赋值 - 2

    我正在做一个项目。目前我有一个相当大的条件语句,它根据一些输入参数为变量赋值。所以,我有这样的东西。ifsomeconditionx=somevalueelsifanotherconditionx=adifferentvalue...重构它的最佳方法是什么?我希望我最终会得到类似的东西x=somevalueifsomecondition||anothervalueifanothercondition这种事情有规律吗? 最佳答案 只需将赋值放在if之外即可。x=ifsomeconditionsomevalueelsifanotherc

  6. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  7. Ruby 并行赋值 - 2

    我想测试一个并行赋值的返回值,我写了puts(x,y=1,2),但是不行,打印错误信息:SyntaxError:(irb):74:syntaxerror,unexpected',',expecting')'puts(x,y=1,2)^(irb):74:syntaxerror,unexpected')',expectingend-of-input有什么问题吗? 最佳答案 你有两个问题。puts和(之间的空格防止括号列表被解释为参数列表。一旦你在方法名后放置一个空格,任何argumentlisthastobeoutsidethepare

  8. ruby - 在 Ruby 中为变量赋值时如何避免控制台输出 - 2

    赋值时是否可以避免这种影响:irb(main):584:0>a=true=>trueirb(main):584:0>我有一个代码有很多赋值,当我试图测试它时,由于所有这些返回值,我看不到结果:truefalsetruefalsetruetrue.. 最佳答案 您可以启动irb或附加--noecho选项的控制台。$irb--noecho2.0.0p353:001>true2.0.0p353:002>否则,如果控制台由另一个进程启动,只需设置conf.echo=false$irb2.0.0p353:001>true=>true2.0.0

  9. ruby-on-rails - 在 Rails 中使用 accepts_nested_attributes_for + 批量赋值保护 - 2

    假设你有这个结构:classHouse请注意,Tv的用户是故意不可访问的。所以你有一个三层嵌套的表单,允许你在一个页面上输入房子、房间和电视。这是Controller的创建方法:defcreate@house=House.new(params[:house])if@house.save#...standardstuffelse#...standardstuffendend问题:您究竟如何为每台电视填充user_id(它应该来自current_user.id)?什么是好的做法?这是我在其中看到的catch22。将user_ids直接填充到params散列中(它们嵌套得很深)保存将失败,因

  10. ruby - 了解 Ruby 中赋值和逻辑运算符的优先级 - 2

    在以下示例中,我无法理解Ruby运算符的优先级:x=1&&y=2由于&&的优先级高于=,我的理解是类似于+和*运算符:1+2*3+4解析为1+(2*3)+4它应该等于:x=(1&&y)=2但是,所有Ruby源代码(包括内部语法解析器Ripper)都将其解析为x=(1&&(y=2))为什么?编辑[08.01.2016]让我们关注一个子表达式:1&&y=2根据优先规则,我们应该尝试将其解析为:(1&&y)=2这没有意义,因为=需要特定的LHS(变量、常量、[]数组项等)。但是既然(1&&y)是一个正确的表达式,那么解析器应该如何处理呢?我试过咨询Ruby的parse.y,但它太像意大利面条

随机推荐