假设我有一堆字符串数组,例如:
data := [4]string{"a", "3.0", "2.5", "10.7"}
和一个结构定义:
type Record struct {
name string
x float64
y float64
mag float64
}
我想从每个数组创建此结构的实例。
我需要将数组的第一项与struct的第一字段进行匹配,依此类推。是否有可能做到这一点? 每个数组对应一个文件的一行,因此我可以实际决定在不同方法更好的情况下如何读取这些值。
答案 0 :(得分:4)
一种简单的方法是使用反射来遍历该结构的字段,获取其地址(指针),然后使用fmt.Sscan()
将字符串值扫描到该字段中。 fmt.Sscan()
将为您处理不同类型的字段。这绝不是一个有效的解决方案,它只是一个简短,简单且灵活的解决方案。如果需要有效的解决方案,则必须手动显式处理所有字段。
这仅在导出结构的字段时有效,例如:
type Record struct {
Name string
X float64
Y float64
Mag float64
Age int
}
将字符串切片加载到结构值中的函数:
func assign(recordPtr interface{}, data []string) error {
v := reflect.ValueOf(recordPtr).Elem()
max := v.NumField()
if max > len(data) {
max = len(data)
}
for i := 0; i < max; i++ {
if _, err := fmt.Sscan(data[i], v.Field(i).Addr().Interface()); err != nil {
return err
}
}
return nil
}
请注意,此实现尝试填充尽可能多的字段(例如,如果结构的字段多于或少于提供的输入数据,则不会返回错误)。还要注意,此assign()
函数可以填充任何其他结构,而不仅仅是Record
,这就是为什么它很灵活的原因。
测试示例:
data := []string{"a", "3.0", "2.5", "10.7", "23"}
var r Record
if err := assign(&r, data); err != nil {
fmt.Println("error:", err)
}
fmt.Printf("%+v", r)
输出(在Go Playground上尝试):
{Name:a X:3 Y:2.5 Mag:10.7 Age:23}
答案 1 :(得分:1)
没有简单的方法可以做到这一点。您必须一个一地分配结构成员。
for _, x := range data {
x, err := strconv.ParseFloat(x[1])
y, err := strconv.ParseFloat(x[2])
max, err := strconv.ParseFloat(x[3])
strData = append(strData, Record{name: x[0], x: x, y: y, mag: mag})
}
您还必须处理解析错误。
答案 2 :(得分:0)
当然可以在Go中做到这一点。
以下代码示例将向s
分配填充有数据字段的记录。
package main
import (
"fmt"
"strconv"
)
type Record struct {
name string
x float64
y float64
mag float64
}
func main() {
data := [4]string{"a", "3.0", "2.5", "10.7"}
x, err := strconv.ParseFloat(data[1], 64)
if err != nil {
panic(err)
}
y, err := strconv.ParseFloat(data[2], 64)
if err != nil {
panic(err)
}
mag, err := strconv.ParseFloat(data[3], 64)
if err != nil {
panic(err)
}
s := Record{ name: data[0], x: x, y: y, mag: mag}
fmt.Println(s)
}