Golang中如何将值数组和头信息反序列化到结构体

Golang中如何将值数组和头信息反序列化到结构体 我正在尝试将CSV中的用户逐一解析到其对应的结构体。但我不确定实现此目标的最佳方式或方法是什么。请查看以下代码。任何帮助都将不胜感激。

recordFile, err := os.Open(csv_file_path)
if err != nil {
	return "Couldnt open file"
}

reader := csv.NewReader(recordFile)
headers, err := reader.Read()
if err != nil {
	return "Couldnt get headers"
}

fmt.Printf("Headers : %v \n", headers)
var user user_schema.User

for i := 0; ; i = i + 1 {
	record, err := reader.Read()
	if err == io.EOF {
		break // reached end of the file
	} else if err != nil {
		return "Error in retrieving record"
	}

	eerr := json.Unmarshal(record, &user) // <- Problem is here, how do I convert headers and array of values to User struct
	if eerr != nil {
		panic(eerr)
	}
}

更多关于Golang中如何将值数组和头信息反序列化到结构体的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

我正在尝试从CSV文件向数据库填充数据(将使其动态化,以便传递任何表结构及其CSV文件路径,即可随时填充数据)。

更多关于Golang中如何将值数组和头信息反序列化到结构体的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


Read 方法返回一个 []string。你需要遍历这个切片(针对表头行)来获取列名。然后针对每一行,遍历该行的 []string 切片。

顺便问一下:user_schema.User 是什么?

// 代码示例应放在这里

lutzhorn:

user_schema.User 是什么?

type User struct {
 ID           uint `gorm:"primary_key"`
 UserName     string `validate:"required"`
 Email        string `validate:"required,email"`
 PwdHash     string `validate:"required" json:"pwd_hash"`
 Password     string `gorm:"-"`
 PhoneNumber  string
 IsActive     int8
 LastActive   string
 CreatedAt    time.Time
 UpdatedAt    time.Time
}

在Golang中,将CSV的头部信息和值数组反序列化到结构体,可以使用reflect包动态映射字段。以下是实现示例:

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "os"
    "reflect"
    "strings"
)

type User struct {
    ID    string `csv:"id"`
    Name  string `csv:"name"`
    Email string `csv:"email"`
}

func UnmarshalCSV(headers []string, record []string, v interface{}) error {
    val := reflect.ValueOf(v).Elem()
    typ := val.Type()

    headerMap := make(map[string]int)
    for i, header := range headers {
        headerMap[strings.ToLower(header)] = i
    }

    for i := 0; i < val.NumField(); i++ {
        field := val.Field(i)
        fieldType := typ.Field(i)

        tag := fieldType.Tag.Get("csv")
        if tag == "" {
            tag = strings.ToLower(fieldType.Name)
        }

        if idx, ok := headerMap[tag]; ok && idx < len(record) {
            field.SetString(record[idx])
        }
    }
    return nil
}

func main() {
    recordFile, err := os.Open("users.csv")
    if err != nil {
        panic(err)
    }
    defer recordFile.Close()

    reader := csv.NewReader(recordFile)
    headers, err := reader.Read()
    if err != nil {
        panic(err)
    }

    fmt.Printf("Headers: %v\n", headers)

    for {
        record, err := reader.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
        }

        var user User
        if err := UnmarshalCSV(headers, record, &user); err != nil {
            panic(err)
        }

        fmt.Printf("User: %+v\n", user)
    }
}

对于更复杂的场景,可以使用第三方库gocarina/gocsv

package main

import (
    "encoding/csv"
    "fmt"
    "os"

    "github.com/gocarina/gocsv"
)

type User struct {
    ID    string `csv:"id"`
    Name  string `csv:"name"`
    Email string `csv:"email"`
}

func main() {
    file, err := os.Open("users.csv")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var users []User
    if err := gocsv.UnmarshalCSV(csv.NewReader(file), &users); err != nil {
        panic(err)
    }

    for _, user := range users {
        fmt.Printf("User: %+v\n", user)
    }
}

如果需要处理动态头部,可以使用mapstructure库:

package main

import (
    "encoding/csv"
    "fmt"
    "io"
    "os"

    "github.com/mitchellh/mapstructure"
)

func main() {
    file, err := os.Open("users.csv")
    if err != nil {
        panic(err)
    }
    defer file.Close()

    reader := csv.NewReader(file)
    headers, err := reader.Read()
    if err != nil {
        panic(err)
    }

    for {
        record, err := reader.Read()
        if err == io.EOF {
            break
        }
        if err != nil {
            panic(err)
        }

        data := make(map[string]interface{})
        for i, header := range headers {
            if i < len(record) {
                data[header] = record[i]
            }
        }

        var user struct {
            ID    string `mapstructure:"id"`
            Name  string `mapstructure:"name"`
            Email string `mapstructure:"email"`
        }

        if err := mapstructure.Decode(data, &user); err != nil {
            panic(err)
        }

        fmt.Printf("User: %+v\n", user)
    }
}

这些示例展示了如何将CSV头部和值数组映射到结构体字段。

回到顶部