Go 语言 Excel 表格转成 Struct
- 最近用go语言的Excelize包实现xlsx读取发现一点问题。当xlsx末尾列数据为空时(下图中红框部分),如果存入到像[]string切片或者数组内,Go语言数组这种会自动忽略右边的空值,会出现行的长度不一致(比如第14行列数为4,15行列数为3,第18行直接没数据)。这比python的pandas难用多了,现总结有几种方法:1.修改原数据(在列末尾添加一个全是一样特殊字符的结束列或者把空cell用特殊字符填充),好处是数据都是对齐,缺点是费时费力。2.代码调整(2.1用数组方式接收字段,接收后需要判断该字段是否空,空就用一个特殊字符替代,然后插入数据库内 2.2用反射的方式实现,用结构体存储,字段为空也不影响)。综合优缺点,开始用2.2方法实现
包的导入
import ( "fmt" "github.com/xuri/excelize/v2" "reflect" "strconv" "strings" )
// 定义结构体 TableColumn, “xlsx"是自定义标签 type TableColumn struct { Classification string `json:"classification" xlsx:"分类"` TagNumber string `json:"tagNumber" xlsx:"标签序号"` FirstlyLabel string `json:"firstlyLabel" xlsx:"一级标签"` SecondaryLabel string `json:"secondaryLabel" xlsx:"二级标签"` TertiaryLabel string `json:"tertiaryLabel" xlsx:"三级标签"` }
// 按行读取数据 func getRows(fileName string) [][]string { file, err := excelize.OpenFile(fileName) if err != nil { panic(err) } defer file.Close() rows, err := file.GetRows(file.GetSheetList()[0], excelize.Options{}) if err != nil { panic(err) } return rows }
// 初始化 标签序列 对应的 结构体字段 顺序 func initTag2FieldIdx(v interface{}, tagKey string) map[string]int { u := reflect.TypeOf(v) numField := u.NumField() tag2fieldIndex := map[string]int{} for i := 0; i < numField; i++ { f := u.Field(i) tagValue, ok := f.Tag.Lookup(tagKey) if ok { tag2fieldIndex[tagValue] = i } else { continue } } return tag2fieldIndex }
// 将 行数据 按照反射的方式转为结构体 TableColumn func rowsToTableColumns(rows [][]string, tag2fieldIndex map[string]int) []*TableColumn { var data []*TableColumn // 默认第一行对应tag head := rows[0] for _, row := range rows[1:] { tbCol := &TableColumn{} rv := reflect.ValueOf(tbCol).Elem() for i := 0; i < len(row); i++ { colCell := row[i] // 通过 tag 取到结构体字段下标 fieldIndex, ok := tag2fieldIndex[head[i]] if !ok { continue } colCell = strings.Trim(colCell, " ") // 通过字段下标找到字段放射对象 v := rv.Field(fieldIndex) // 根据字段的类型,选择适合的赋值方法 switch v.Kind() { case reflect.String: value := colCell v.SetString(value) case reflect.Int64, reflect.Int32: value, err := strconv.Atoi(colCell) if err != nil { panic(err) } v.SetInt(int64(value)) case reflect.Float64: value, err := strconv.ParseFloat(colCell, 64) if err != nil { panic(err) } v.SetFloat(value) } } data = append(data, tbCol) } return data }
func main() { initTag2FieldIdx := initTag2FieldIdx(TableColumn{}, "xlsx") rows := getRows("excel/test.xlsx") tbCols := rowsToTableColumns(rows, initTag2FieldIdx) for _, s := range tbCols { fmt.Printf("%+v\n", s) } }
结果:
参考:
1. 小试牛刀:Go 反射帮我把 Excel 转成 Struct - Zioyi - 博客园 (cnblogs.com)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了