You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过反射实现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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 12:54:03