在main范围内访问内部范围内的结构数据并在Golang中保存为csv

问题描述:

appendStruct函数被设计为在多个线程中运行,以便收集和追加DataItemDataContainer。到目前为止,我可以从内部打印结果appendStruct Q1:如何从main访问和打印container,Q2:将结构数据类型从main保存到csv?从go run test.go在main范围内访问内部范围内的结构数据并在Golang中保存为csv

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() 

} 

输出是:

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

重新Q1。 "encoding/csv"必须实现字符串接口[][]string有一个提示如何在Write struct to csv file 中接近它,但缺少实现示例。

+1

从'appendStruct'返回'container'。 – RayfenWindspear

+0

请问你能解决这个问题吗?我是'golang'的新手。我将有多个'appendStruct'线程将数据写入'container',所以当它们全部完成时需要被访问。 –

appendStruct,container是一个局部变量,所以它不能在该函数调用之外访问。你可以退货,这将使它从呼叫者访问(在这种情况下,main):

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

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

您链接答案是一个很好的起点。一个代码示例应该不是必须的 - 它们基本上建议您创建一个帮助器方法/函数,该方法/函数将结构中的所有字段放入切片中,并按照您希望它们显示在CSV中的顺序放入切片中,例如:

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 
} 

然后,您可以循环这些以将它们写入CSV文件。

你得到的错误输出是因为你使用的是Sprintf,它需要一个格式字符串作为第一个参数,并且每个参数都有一个引用。你传递一个空格式字符串,它只能在没有其他参数的情况下工作(并且毫无意义)。也许你的意思是Sprintf("%v", container)或只是Sprint(container)

谢谢@阿德里安,你的回答非常有帮助。以下是工作代码:

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) 
}