使用反射(reflect)来设置结构体中的结构体值。

huangapple go评论63阅读模式
英文:

Use reflect to set values of struct of struct values

问题

我有一些代码,看起来工作正常,但最终没有任何效果:

http://play.golang.org/p/TfAWWy4-R8

有一个结构体,其中包含结构体类型的字段。内部结构体具有所有字符串字段。

在循环中使用反射,想要从外部结构体中获取所有结构体字段。然后,填充内部结构体的所有字符串值。示例代码从标签中获取文本,并在“,”上进行解析,以获取内部循环的字符串值。

这是应该创建内部结构体并将解析的数据添加到字符串值的主要部分。

t := reflect.TypeOf(Alias{})
alias = reflect.New(t)
for i := 0; i < alias.Elem().NumField(); i++ {
   p := alias.Elem().Field(i)
   p.SetString(params[i])
}

当查看示例的输出时,似乎它正在工作,但在打印外部结构体的值后,它似乎是空的:

fmt.Println("Final01 = ", Attr.Final01.Command) // 打印空字符串

所以不确定如何将值传递给内部结构体Alias{}

谢谢任何帮助。

英文:

I have some code that looks to be working but does nothing in the end:

http://play.golang.org/p/TfAWWy4-R8

Have a struct that has fields of type struct. The inner struct has all string fields.

Using reflect in a loop, want to get all struct fields from outer struct. Next, populate all string values in inner struct. the example code is getting text from the tags and parsing it on "," to get strings values for inner loop.

This is the main part that should create the inner struct and add the parsed data to the string values.

    t := reflect.TypeOf(Alias{})
	alias = reflect.New(t)
    for i := 0; i &lt; alias.Elem().NumField(); i++ {
       p := alias.Elem().Field(i)
	   p.SetString(params[i])
    }

It looks like it is working when you look at the output from example, but after printing a value from outer struct it seems to be empty:

fmt.Println(&quot;Final01 = &quot;, Attr.Final01.Command) // prints empty string

So not sure how to get values into the inner struct Alias{}

Thanks for any help.

答案1

得分: 2

这是工作程序。下面是解释。

package main

import "fmt"
import "strings"
import "reflect"

type Alias struct {
    Name         string
    DevicePath   string
    GuiPath      string
    Setpoint     string
    Command      string
    Status       string
    FunctionCmds string
}

type Manifold struct {
    Final01    Alias "Final01,/Gaspanel/Shared/Final01,,,wOpen,rIsOpen,"
    Dump01     Alias "Dump01,/Gaspanel/Shared/Dump01,,,wOpen,rIsOpen,"
    N2Vent01   Alias "N2Vent01,/Gaspanel/Shared/N2Vent01,,,wOpen,rIsOpen,"
    N2Vent201  Alias "N2Vent201,/Gaspanel/Shared/N2Vent201,,,wOpen,rIsOpen,"
    PurgeValve Alias "PurgeValve,/Gaspanel/Shared/Purge01,,,wOpen,rIsOpen,"
}

func MapTagedAliasToChamber(chamber string, struc interface{}) []string {
    attributeStruct := reflect.ValueOf(struc).Elem()
    typeAttributeStruct := attributeStruct.Type()
    attributes := make([]string, attributeStruct.NumField(), attributeStruct.NumField())
    for i := 0; i < attributeStruct.NumField(); i++ {
        alias := attributeStruct.Field(i)
        tag := string(typeAttributeStruct.Field(i).Tag)
        name := typeAttributeStruct.Field(i).Name
        params := strings.Split(tag, ",")
        alias = reflect.New(reflect.TypeOf(Alias{})).Elem()
        for i := 0; i < alias.NumField(); i++ {
            alias.Field(i).SetString(params[i])
        }
        attributeStruct.Field(i).Set(alias)
        fmt.Printf("%d: %s %s = %v\n", i, name, alias.Type(), alias.Interface())
    }

    return attributes
}

func main() {
    Attr := Manifold{}
    MapTagedAliasToChamber("A", &Attr)

    fmt.Println("Final01 = ", Attr.Final01.Command)

}

你原始程序的问题在于第38行,你创建了一个名为alias的新的reflect.Value,表示*Alias类型的值,然后填充了你的信息,但没有将其写回到Manifold结构体中。

此外,我建议你坚持使用标准的结构体标签格式,可以通过(reflect.StructTag).Get(key string)更容易地解析和使用它们。在不需要的地方不要使用字符串,例如rIsOpen听起来像是一个布尔值。

英文:

Here's the working program. Explanation below.

package main
import &quot;fmt&quot;
import &quot;strings&quot;
import &quot;reflect&quot;
type Alias struct {
Name         string
DevicePath   string
GuiPath      string
Setpoint     string
Command      string
Status       string
FunctionCmds string
}
type Manifold struct {
Final01    Alias &quot;Final01,/Gaspanel/Shared/Final01,,,wOpen,rIsOpen,&quot;
Dump01     Alias &quot;Dump01,/Gaspanel/Shared/Dump01,,,wOpen,rIsOpen,&quot;
N2Vent01   Alias &quot;N2Vent01,/Gaspanel/Shared/N2Vent01,,,wOpen,rIsOpen,&quot;
N2Vent201  Alias &quot;N2Vent201,/Gaspanel/Shared/N2Vent201,,,wOpen,rIsOpen,&quot;
PurgeValve Alias &quot;PurgeValve,/Gaspanel/Shared/Purge01,,,wOpen,rIsOpen,&quot;
}
func MapTagedAliasToChamber(chamber string, struc interface{}) []string {
attributeStruct := reflect.ValueOf(struc).Elem()
typeAttributeStruct := attributeStruct.Type()
attributes := make([]string, attributeStruct.NumField(), attributeStruct.NumField())
for i := 0; i &lt; attributeStruct.NumField(); i++ {
alias := attributeStruct.Field(i)
tag := string(typeAttributeStruct.Field(i).Tag)
name := typeAttributeStruct.Field(i).Name
params := strings.Split(tag, &quot;,&quot;)
alias = reflect.New(reflect.TypeOf(Alias{})).Elem()
for i := 0; i &lt; alias.NumField(); i++ {
alias.Field(i).SetString(params[i])
}
attributeStruct.Field(i).Set(alias)
fmt.Printf(&quot;%d: %s %s = %v\n&quot;, i, name, alias.Type(), alias.Interface())
}
return attributes
}
func main() {
Attr := Manifold{}
MapTagedAliasToChamber(&quot;A&quot;, &amp;Attr)
fmt.Println(&quot;Final01 = &quot;, Attr.Final01.Command)
}

The problem was on line 38 of your original program, where you created a new reflect.Value named alias representing a value of type *Alias, then filled it with your information but never wrote it back into your Manifold struct.

Additionally I suggest that you stick to the standard struct-tag format which can be parsed and used more easily through (reflect.StructTag).Get(key string). And don't use strings where you don't need them e.g. rIsOpen sounds like a boolean value to me.

huangapple
  • 本文由 发表于 2014年11月21日 10:44:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/27053305.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定