在main范围内访问内部范围内的结构数据并在Golang中保存为csv
问题描述:
appendStruct
函数被设计为在多个线程中运行,以便收集和追加DataItem
到DataContainer
。到目前为止,我可以从内部打印结果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 中接近它,但缺少实现示例。
答
在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)
}
从'appendStruct'返回'container'。 – RayfenWindspear
请问你能解决这个问题吗?我是'golang'的新手。我将有多个'appendStruct'线程将数据写入'container',所以当它们全部完成时需要被访问。 –