在 Go 中实现 struct-to-csv 编写器

以下代码尝试为任何简单结构实现通用 CSV 编写器。“简单”是指结构的字段值是标准的简单类型(int、string 等)。


type (

    CSV interface {

        Header() []string

        String([]string) (string, error)

    }

    CSVArray []CSV

)



func CSVOutput(w io.Writer, data CSVArray, cols []string) error {

    if len(data) == 0 {

        return nil

    }

    _, err := fmt.Fprintln(w, data[0].Header())

    if err != nil {

        return err

    }

    for _, d := range data {

        str, err := d.String(cols)

        if err != nil {

            return err

        }

        _, err = fmt.Fprintln(w, str)

        if err != nil {

            return err

        }

    }

    return nil

}

问题是CSVOutput()实际上不起作用。例如:


var data []Employee //the Employee struct implements CSV interface

CSVOutput(w, data, nil)

编译失败:cannot use data (type []Employee) as type CSVArray in argument to CSVOutput


我了解 []CSV 与 []Employee 不同,如此处所述,以及许多其他在线可用资源。


也就是说,是否可以CSVOutput()使用反射重写函数:


func CSVOutput(w io.Writer, data interfac{}, cols []string) error {

    sliceOfIntf = castToSlice(data) //how to do this?

    if !implementedCSV(sliceOfIntf[0]) { //and how to do this?

        return errors.New("not csv")

    }

    ... ...

}


慕妹3146593
浏览 153回答 1
1回答

慕容森

是否可以使用反射重写 CSVOutput() 函数是的// if data is []Employee{...}, then you can do the following:rv := reflect.ValueOf(data)if rv.Kind() != reflect.Slice {&nbsp; &nbsp; return fmt.Errorf("data is not slice")}if !rv.Type().Elem().Implements(reflect.TypeOf((*CSV)(nil)).Elem()) {&nbsp; &nbsp; return fmt.Errorf("slice element does not implement CSV")}csvArr := make(CSVArray, rv.Len())for i := 0; i < rv.Len(); i++ {&nbsp; &nbsp; csvArr[i] = rv.Index(i).Interface().(CSV)}// now csvArr is CSVArray containing all the elements of datahttps://go.dev/play/p/gcSOid533gx
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go