如何通过反射实现Go语言通用结构体转CSV写入功能
Go 通用CSV写入工具反射实现方案
package main import ( "errors" "fmt" "io" "reflect" ) // 原有接口定义保持不变 type CSV interface { Header() []string String(cols []string) (string, error) } // 重写后的通用CSVOutput函数 func CSVOutput(w io.Writer, data interface{}, cols []string) error { // 1. 校验入参是否为切片 v := reflect.ValueOf(data) if v.Kind() != reflect.Slice { return errors.New("data must be a slice") } // 2. 空切片直接返回 length := v.Len() if length == 0 { return nil } // 3. 校验切片元素是否实现了CSV接口 firstElem := v.Index(0).Interface() if _, ok := firstElem.(CSV); !ok { return errors.New("slice element does not implement CSV interface") } // 4. 输出表头 header := firstElem.(CSV).Header() _, err := fmt.Fprintln(w, header) if err != nil { return err } // 5. 遍历输出每行数据 for i := 0; i < length; i++ { elem := v.Index(i).Interface().(CSV) line, err := elem.String(cols) if err != nil { return err } if _, err := fmt.Fprintln(w, line); err != nil { return err } } return nil }
关键实现说明
- 切片类型校验:通过
reflect.ValueOf(data).Kind()判断入参是否为切片类型,不符合直接返回错误 - 接口实现校验:通过类型断言
firstElem.(CSV)判断切片元素是否满足CSV接口约束,避免运行时panic - 切片元素遍历:通过反射的
Index(i)方法逐个取出切片元素,转换为CSV接口后调用对应方法
调用示例
原来的调用代码无需修改即可正常运行:
// Employee已实现CSV接口 var data []Employee // 直接传入[]Employee类型即可,无需手动转换为[]CSV err := CSVOutput(w, data, nil)
可选优化建议
原有实现直接用fmt.Fprintln输出表头和行数据,会默认用空格分隔元素且带上方括号,不符合标准CSV格式,建议替换为标准库encoding/csv的Writer处理输出,自动处理逗号分隔、特殊字符转义等逻辑:
// 替换表头输出逻辑示例 csvWriter := csv.NewWriter(w) defer csvWriter.Flush() if err := csvWriter.Write(header); err != nil { return err }
内容的提问来源于stack exchange,提问作者xrfang
相关产品推荐
相关产品推荐

