0

appendStruct function is designed to run in multiple threads in order to collect and append DataItem into DataContainer. So far I can print the result from inner appendStruct Q1: how to access and print container from main, Q2: save that struct data type to csv from main ?

package main

import "fmt"

type DataItem struct {
    name string
}

type DataContainer struct {
    Items []DataItem
}

func (box *DataContainer) AddItem(item DataItem) []DataItem {
    box.Items = append(box.Items, item)
    return box.Items
}

func appendStruct() {
    items := []DataItem{}
    container := DataContainer{items}

    item1 := DataItem{name: fmt.Sprintf("Item1")}
    item2 := DataItem{name: fmt.Sprintf("Item2")}

    container.AddItem(item1)
    container.AddItem(item2)

    var ss = fmt.Sprintf("", container)
    fmt.Println(ss)
}

func main() {

    appendStruct()

}

OUTPUT from go run test.go is:

%!(EXTRA main.DataContainer={[{Item1} {Item2}]})

re Q1. "encoding/csv" has to implement string interface [][]string there is a hint how to approach it in Write struct to csv file but lacks implementation example.

2
  • 1
    Return container from appendStruct. Commented Aug 2, 2017 at 16:50
  • Could you hind the solution please? I am new to golang. I will have multiple appendStruct threads writing data to container, so it needs to be accessed when they are all completed. Commented Aug 2, 2017 at 16:57

2 Answers 2

2

In appendStruct, container is a local variable, so it's not accessible outside that function call. You could return it, which would make it accessible from the caller (in this case, main):

func appendStruct() DataContainer {
    //...
    return container
}

func main() {
    container := appendStruct()
}

The answer you linked is an excellent starting point. A code example shouldn't really be necessary - they're basically recommending that you create a helper method/function that takes all the fields of the struct and puts them into a slice in whatever order you want them to appear in the CSV, e.g.:

func (c DataItem) ToSlice() []string {
    row := make([]string, 1, 1) // Since you only have 1 field in the struct
    row[0] = c.name
    return row
}

Then you can loop over these to write them to a CSV file.

The error output you're getting is because you're using Sprintf, which expects a format string as the first parameter with a reference for each other argument. You're passing an empty format string, which would only work with no other arguments (and be pointless). Perhaps you meant Sprintf("%v", container) or just Sprint(container)?

Sign up to request clarification or add additional context in comments.

Comments

0

Thank you @Adrian, your answer was very helpful. Below is working code:

package main

import (
   "fmt"
   "os"
   "encoding/csv"
   "log"
)

type DataItem struct {
     name string
}

type DataContainer struct {
     Items []DataItem
}

func (box *DataContainer) AddItem(item DataItem) []DataItem {
     box.Items = append(box.Items, item)
     return box.Items
}

func appendStruct() DataContainer{
      items := []DataItem{}
      container := DataContainer{items}

      item1 := DataItem{name: fmt.Sprintf("Item1")}
      item2 := DataItem{name: fmt.Sprintf("Item2")}

       container.AddItem(item1)
       container.AddItem(item2)

return container
}


func (c DataItem) ToSlice() []string {
     row := make([]string, 1, 1)
     row[0] = c.name
 return row
}

func checkError(message string, err error) {
    if err != nil {
    log.Fatal(message, err)
     }
}


func main() {

container := appendStruct()

var ss = fmt.Sprint(container)
println(ss)


file, err := os.Create("result.csv")
checkError("Cannot create file", err)
defer file.Close()

w := csv.NewWriter(file)

for _, record := range container.Items {
    values := record.ToSlice()
    if err := w.Write(values); err != nil {
        log.Fatalln("error writing record to csv:", err)
    }
}

w.Flush()

if err := w.Error(); err != nil {
    log.Fatal(err)
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.