[英]How to create a Golang struct instance from an array?
假设我有一堆字符串数组,例如:
data := [4]string{"a", "3.0", "2.5", "10.7"}
和一个结构定义:
type Record struct {
name string
x float64
y float64
mag float64
}
我想从每个数组创建这个结构的实例。
我需要将数组的第一项与结构的第一个字段相匹配,依此类推。 是否有可能做到这一点? 每个数组对应于文件的一行,因此我实际上可以决定如何读取这些值,以防不同的方法更好。
一种简单的方法是使用反射遍历结构体的字段,获取它们的地址(指针),然后使用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}
没有简单的方法可以做到这一点。 您必须一一分配结构成员。
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})
}
您还必须处理解析错误。
当然,在 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)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.