以编程方式填充 golang 结构

我有一个包含多种类型数据记录的文件,我需要将其解析为结构。

我很高兴了解一种按记录类型填充结构的惯用方法(如果存在)。类似于 python 的namedtuple(*fields)构造函数。

package main


import (

    "fmt"

    "strconv"

    "strings"

)


type X interface{}


type HDR struct {

    typer, a string

    b        int

}


type BDY struct {

    typer, c string

    d        int

    e        string

}


var lines string = `HDR~two~5

BDY~four~6~five`


func sn(s string) int {

    i, _ := strconv.Atoi(s)

    return i

}


func main() {

    sl := strings.Split(lines, "\n")

    for _, l := range sl {

        fields := strings.Split(l, "~")

        var r X

        switch fields[0] {

        case "HDR":

            r = HDR{fields[0], fields[1], sn(fields[2])} // 1

        case "BDY":

            r = BDY{fields[0], fields[1], sn(fields[2]), fields[3]} // 2

        }

        fmt.Printf("%T : %v\n", r, r)

    }

}

我特别感兴趣的是了解是否标记了行// 1并// 2可以方便地用代码替换,也许是某种允许结构本身处理类型转换的通用解码器。


森栏
浏览 131回答 1
1回答

斯蒂芬大帝

使用Reflect包以编程方式设置字段。必须导出一个字段才能由反射包设置。通过将名称中的第一个符文大写来导出名称:type HDR struct {    Typer, A string    B        int}type BDY struct {    Typer, C string    D        int    E        string}创建名称到与名称关联的类型的映射:var types = map[string]reflect.Type{    "HDR": reflect.TypeOf((*HDR)(nil)).Elem(),    "BDY": reflect.TypeOf((*BDY)(nil)).Elem(),}对于每一行,使用映射创建一个类型的值types:for _, l := range strings.Split(lines, "\n") {    fields := strings.Split(l, "~")    t := types[fields[0]]    v := reflect.New(t).Elem()    ...}循环遍历该行中的字段。获取字段值,将字符串转换为字段值的种类并设置字段值:    for i, f := range fields {        fv := v.Field(i)        switch fv.Type().Kind() {        case reflect.String:            fv.SetString(f)        case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:            n, _ := strconv.ParseInt(f, 10, fv.Type().Bits())            fv.SetInt(n)        }    }这是该方法的基本轮廓。错误处理值得注意:如果类型名称不是中提到的类型之一,应用程序将出现恐慌types;应用程序忽略解析整数返回的错误;如果数据中的字段多于结构体,应用程序将会出现恐慌;当应用程序遇到不支持的字段类型时,不会报告错误;和更多。在 Go Playground 上运行它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go