繁体   English   中英

如何从数组创建 Golang 结构体实例?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM