gocarina / gocsv

The GoCSV package aims to provide easy CSV serialization and deserialization to the golang programming language
MIT License
1.95k stars 243 forks source link

Circular links between structs lead to massive memory consumption and a killed program #278

Open SetorHabona opened 1 month ago

SetorHabona commented 1 month ago

As the title says, using a struct schema which has circular links (as can happen using an ORM like GORM), the memory usage explodes and the program is killed. I have created a small repo with the minimal code to reproduce the issue. I have also attached some code directly below. https://github.com/SetorHabona/gocsv-mem-leak

NOTE: An easy fix is excluding the inner struct using csv:"-"

package main

import (
    "fmt"
    "os"

    "github.com/gocarina/gocsv"
)

// this setup is not not very unusual when working with gorm (maybe also other ORMs)
type Wrapper struct {
    Name string `csv:"name"`
    Age  uint   `csv:"age"`
    // Inner creates a problem, both as pointer and as value
    Inner *Inner // add `csv:"-"` to avoid rapid increase in consumed memory and your program being killed
}

type Inner struct {
    Position string
    Salary   uint
    Wrappers *Wrapper
}

func main() {
    file, err := os.OpenFile("./data.csv", os.O_RDWR|os.O_CREATE, os.ModePerm)
    if err != nil {
        panic(err)
    }
    defer file.Close()

    var wraps []Wrapper
    if err := gocsv.UnmarshalFile(file, &wraps); err != nil {
        panic(err)
    }
    fmt.Printf("%+v\n", wraps)
}