在从CSV文件读取时,在API响应中添加一行额外的内容。

huangapple go评论79阅读模式
英文:

Go adding a extra line in API response when reading from a csv file

问题

当通过我的前端(React)上传文件时,Go语言会读取CSV文件,然后以结构化的格式将数据发送到JSON响应中。

JSON响应:

{
    "Success": true,
    "labels": [
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec"
    ],
    "data": [
        {
            "label": "",
            "data": null,
            "borderColor": "",
            "backgroundColor": ""
        },
        {
            "label": "Kyle",
            "data": [
                "1517",
                "1689",
                "1719",
                "1591",
                "1490",
                "1310",
                "1533",
                "1500",
                "1400",
                "1300",
                "1600",
                "1800"
            ],
            "borderColor": "#f6ff00",
            "backgroundColor": "#f6ff00"
        },
        {
            "label": "Mickey",
            "data": [
                "3000",
                "3100",
                "3200",
                "3000",
                "3500",
                "4000",
                "3700",
                "3500",
                "3000",
                "4000",
                "5000",
                "4000"
            ],
            "borderColor": "#ff0000",
            "backgroundColor": "#ff0000"
        },
        {
            "label": "Donald",
            "data": [
                "2500",
                "2000",
                "2800",
                "3000",
                "3100",
                "2900",
                "2800",
                "3000",
                "3200",
                "3400",
                "3500",
                "3800"
            ],
            "borderColor": "#001eff",
            "backgroundColor": "#001eff"
        }
    ]
}

你可以看到问题出在data字段下的这一行:

{"label":"","data":null,"borderColor":"","backgroundColor":""}

我不知道为什么Go会添加这一行。

CSV文件:

,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
Kyle,1517,1689,1719,1591,1490,1310,1533,1500,1400,1300,1600,1800
Mickey,3000,3100,3200,3000,3500,4000,3700,3500,3000,4000,5000,4000
Donald,2500,2000,2800,3000,3100,2900,2800,3000,3200,3400,3500,3800
func RouteUpload(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {

	r.ParseMultipartForm(16 * 1024 * 1024) // 16MB
	file, handler, err := r.FormFile("file")
	if err != nil {
		w.WriteHeader(http.StatusBadRequest)
		return
	}
	defer file.Close()

	// 在文件系统上创建一个空文件
	f, err := os.OpenFile(filepath.Join("uploads", handler.Filename), os.O_WRONLY|os.O_CREATE, 0666)
	defer f.Close()

	// 将文件复制到images目录中
	io.Copy(f, file)
	w.Header().Set("Content-Type", "application/json")

	type MyData struct {
		Label           string   `json:"label"`
		Data            []string `json:"data"`
		BorderColor     string   `json:"borderColor"`
		BackgroundColor string   `json:"backgroundColor"`
	}

	type MyFile struct {
		Success bool     `json:"Success"`
		Labels  []string `json:"labels"`
		Data    []MyData `json:"data"`
	}

	var myData MyData
	var myFile MyFile

	path := "uploads/" + handler.Filename

	// 打开文件
	fi, err := os.Open(path)
	if err != nil {
		log.Fatal(err)
	}

	// 程序结束时记得关闭文件
	defer f.Close()

	// 使用csv.Reader读取csv值
	csvReader := csv.NewReader(fi)
	data, err := csvReader.ReadAll()
	if err != nil {
		fmt.Println(err)
	}

	colors := []string{"#00ff12", "#f6ff00", "#ff0000", "#001eff", "#ea00ff", "#ff9600"}

	for i, line := range data {
		if i == 0 {
			for j, field := range line {
				if j == 0 {

				} else {
					myFile.Labels = append(myFile.Labels, field)
				}
			}
		} else {
			fmt.Println(line)
			for j, field := range line {
				if j == 0 {
					myData.Label = field
				} else {
					myData.Data = append(myData.Data, field)
				}
			}
			myData.BorderColor = colors[i]
			myData.BackgroundColor = colors[i]
		}
		myFile.Data = append(myFile.Data, myData)
		myData.Data = []string{}
	}

	myFile.Success = true

	// 转换为JSON格式
	responseJson, err := json.Marshal(myFile)
	if err != nil {
		fmt.Println(err)
	}

	// 以JSON格式发送成功响应给用户
	fmt.Fprintf(w, "%s\n", responseJson)
}
英文:

When uploading a file through my frontend (React), Go is reading the csv file and then sending the data in a structured format in a JSON response.

The JSON response:

{
"Success": true,
"labels": [
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
],
"data": [
{
"label": "",
"data": null,
"borderColor": "",
"backgroundColor": ""
},
{
"label": "Kyle",
"data": [
"1517",
"1689",
"1719",
"1591",
"1490",
"1310",
"1533",
"1500",
"1400",
"1300",
"1600",
"1800"
],
"borderColor": "#f6ff00",
"backgroundColor": "#f6ff00"
},
{
"label": "Mickey",
"data": [
"3000",
"3100",
"3200",
"3000",
"3500",
"4000",
"3700",
"3500",
"3000",
"4000",
"5000",
"4000"
],
"borderColor": "#ff0000",
"backgroundColor": "#ff0000"
},
{
"label": "Donald",
"data": [
"2500",
"2000",
"2800",
"3000",
"3100",
"2900",
"2800",
"3000",
"3200",
"3400",
"3500",
"3800"
],
"borderColor": "#001eff",
"backgroundColor": "#001eff"
}
]
}

You see the problem is this line under data:

{"label":"","data":null,"borderColor":"","backgroundColor":""}

I do not know why this is being added in by Go

The CSV file:

,Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec
Kyle,1517,1689,1719,1591,1490,1310,1533,1500,1400,1300,1600,1800
Mickey,3000,3100,3200,3000,3500,4000,3700,3500,3000,4000,5000,4000
Donald,2500,2000,2800,3000,3100,2900,2800,3000,3200,3400,3500,3800
func RouteUpload(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
r.ParseMultipartForm(16 * 1024 * 1024) // 16MB
file, handler, err := r.FormFile("file")
if err != nil {
w.WriteHeader(http.StatusBadRequest)
return
}
defer file.Close()
// Create an empty file on filesystem
f, err := os.OpenFile(filepath.Join("uploads", handler.Filename), os.O_WRONLY|os.O_CREATE, 0666)
defer f.Close()
// Copy the file to the images directory
io.Copy(f, file)
w.Header().Set("Content-Type", "application/json")
type MyData struct {
Label           string   `json:"label"`
Data            []string `json:"data"`
BorderColor     string   `json:"borderColor"`
BackgroundColor string   `json:"backgroundColor"`
}
type MyFile struct {
Success bool     `json:"Success"`
Labels  []string `json:"labels"`
Data    []MyData `json:"data"`
}
var myData MyData
var myFile MyFile
path := "uploads/" + handler.Filename
// open file
fi, err := os.Open(path)
if err != nil {
log.Fatal(err)
}
// remember to close the file at the end of the program
defer f.Close()
// read csv values using csv.Reader
csvReader := csv.NewReader(fi)
data, err := csvReader.ReadAll()
if err != nil {
fmt.Println(err)
}
colors := []string{"#00ff12", "#f6ff00", "#ff0000", "#001eff", "#ea00ff", "#ff9600"}
for i, line := range data {
if i == 0 {
for j, field := range line {
if j == 0 {
} else {
myFile.Labels = append(myFile.Labels, field)
}
}
} else {
fmt.Println(line)
for j, field := range line {
if j == 0 {
myData.Label = field
} else {
myData.Data = append(myData.Data, field)
}
}
myData.BorderColor = colors[i]
myData.BackgroundColor = colors[i]
}
myFile.Data = append(myFile.Data, myData)
myData.Data = []string{}
}
myFile.Success = true
// Marshal into JSON
responseJson, err := json.Marshal(myFile)
if err != nil {
fmt.Println(err)
}
// Send success response to user in JSON
fmt.Fprintf(w, "%s\n", responseJson)
}

答案1

得分: 1

你正在对CSV文件的第一行进行不同处理,因为有if i==0 {...} else {...},但之后你总是将数据追加到myFile.Data中 - 所以对于i==0,空的myData也会被追加。尝试将这个追加操作移到else块中。

还有一些建议:在Go语言中,实际上不鼓励使用if ... else(参见https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88)。所以对于if i==0,你可以在for循环后使用continue来避免使用else - 然后你可以将代码移到else块外部。另外,if j==0 {/*do nothing*/} else {/*do something*/}应该改为if j!=0 {/*do something*/}

英文:

You are treating the first line from the CSV file differently than the others because of the if i==0 {...} else {...}, but after that you are always appending to myFile.Data - so for i==0, the empty myData will be appended. Try moving this append into the else block.

Some other suggestions: if ... else is actually discouraged in Go (see https://medium.com/@matryer/line-of-sight-in-code-186dd7cdea88). So for the if i==0, you could avoid the else by using continue after the for loop - then you could move the code out of the else block. Also, the if j==0 {/*do nothing*/} else {/*do something*/} should of course be if j!=0 {/*do something*/}.

huangapple
  • 本文由 发表于 2022年2月22日 00:18:32
  • 转载请务必保留本文链接:https://go.coder-hub.com/71209644.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定