英文:
Write/Save data in CSV using GO language
问题
我正在尝试在Go语言中将学生分数写入CSV文件。
使用Println
打印出了每页所需的10个结果,但只保存了最后一个值(而不是所有10个值)到CSV文件中。
这是我的做法:
-
访问者访问
studentmarks.com/page=1
。
显示10个学生的分数,并保存到CSV文件中。 -
访问者点击下一页,导航到
studentmarks.com/page=2
。
显示另外10个学生的分数,并在CSV文件中保存到相应的列/行。
以此类推。
fmt.Fprintf(w, KeyTemplate, key.fname, key.marks, key.lname)
可以正常工作,并在每页显示所有10个结果,但我无法将所有10个结果保存到CSV文件中(使用当前的代码,只保存了最后一个结果)。
以下是负责打印和保存结果的代码片段:
func PageRequest(w http.ResponseWriter, r *http.Request) {
// 默认页面编号为1
if len(r.URL.Path) <= 1 {
r.URL.Path = "/1"
}
// 页面编号不能为负数或0
page.Abs(page)
if page.Cmp(one) == -1 {
page.SetInt64(1)
}
// 页面头部
fmt.Fprintf(w, PageHeader, pages, previous, next)
// 计算UID的分数
UID, length := compute(start)
for i := 0; i < length; i++ {
key := UID[i]
fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)
// 保存到CSV文件
csvfile, err := os.Create("marks.csv")
if err != nil {
fmt.Println("Error:", err)
return
}
defer csvfile.Close()
records := [][]string{{key.fname, key.marks, key.lname, key.remarks}}
writer := csv.NewWriter(csvfile)
for _, record := range records {
err := writer.Write(record)
if err != nil {
fmt.Println("Error:", err)
return
}
}
writer.Flush()
}
// 页面底部
fmt.Fprintf(w, PageFooter, previous, next)
}
如何使用Go语言打印和保存(到CSV文件)所有10个结果?
英文:
I am trying to write Student Marks to a csv file in GO .
It is printing the desired 10 result per page with Println
but is saving only the last value (not all 10) in csv .
This is what I am doing
-
Visitor visits
studentmarks.com/page=1
Marks for 10 students are displayed and it is also saved in CSV -
Visitor clicks next page and he is navigated to
studentmarks.com/page=2
Marks for another 10 students are displayed and it is also saved in subsequent column/rows in the CSV
and so on
fmt.Fprintf(w, KeyTemplate, key.fname, key.marks, key.lname )
is working fine and displays all 10 results per page but I am unable to save all 10 results in the CSV (with my current code, only the last result is saved).
Here is my snippet of the code that is responsible for printing and saving the results.
func PageRequest(w http.ResponseWriter, r *http.Request) {
// Default page number is 1
if len(r.URL.Path) <= 1 {
r.URL.Path = "/1"
}
// Page number is not negative or 0
page.Abs(page)
if page.Cmp(one) == -1 {
page.SetInt64(1)
}
// Page header
fmt.Fprintf(w, PageHeader, pages, previous, next)
// Marks for UID
UID, length := compute(start)
for i := 0; i < length; i++ {
key := UID[i]
fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)
// Save in csv
csvfile, err := os.Create("marks.csv")
if err != nil {
fmt.Println("Error:", err)
return
}
defer csvfile.Close()
records := [][]string{{key.fname, key.marks, key.lname, , key.remarks}}
writer := csv.NewWriter(csvfile)
for _, record := range records {
err := writer.Write(record)
if err != nil {
fmt.Println("Error:", err)
return
}
}
writer.Flush()
// Page Footer
fmt.Fprintf(w, PageFooter, previous, next)
}
How can I print and save (in csv) all the 10 results using go language?
答案1
得分: 1
基本问题是你正在调用 os.Create。os.Create 的文档中说:
> Create 使用模式 0666(在 umask 之前)创建具有指定名称的文件,如果文件已经存在,则截断它。如果成功,返回的 File 上的方法可用于 I/O;关联的文件描述符具有 O_RDWR 模式。如果出现错误,它将是 *PathError 类型。
因此,每次调用 os.Create 都会删除传递的文件中的所有内容。相反,你可能想要使用 os.OpenFile 以及 os.O_CREATE、os.O_WRONLY 和 os.O_APPEND 标志。这样可以确保文件将被创建(如果不存在),但不会截断它。
但是你的代码中还有另一个问题。你在循环内部调用了 defer csvfile.Close()
。延迟函数只有在函数返回后才会执行一次,而不是在循环迭代之后执行。这可能会导致问题,特别是因为你一遍又一遍地打开同一个文件。
相反,你应该在循环之前打开文件,这样你只需要在循环结束后关闭它。像这样:
package main
import (
"encoding/csv"
"fmt"
"net/http"
"os"
)
func PageRequest(w http.ResponseWriter, r *http.Request) {
// 默认页面编号为 1
if len(r.URL.Path) <= 1 {
r.URL.Path = "/1"
}
// 页面编号不能为负数或 0
page.Abs(page)
if page.Cmp(one) == -1 {
page.SetInt64(1)
}
// 页面头部
fmt.Fprintf(w, PageHeader, pages, previous, next)
// 保存到 CSV 文件
csvfile, err := os.OpenFile("marks.csv", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Println("错误:", err)
return
}
defer csvfile.Close()
writer := csv.NewWriter(csvfile)
defer writer.Flush()
// UID 的分数
UID, length := compute(start)
for i := 0; i < length; i++ {
key := UID[i]
fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)
records := [][]string{{key.fname, key.marks, key.lname, key.remarks}}
for _, record := range records {
err := writer.Write(record)
if err != nil {
fmt.Println("错误:", err)
return
}
}
}
// 页面底部
fmt.Fprintf(w, PageFooter, previous, next)
}
英文:
The basic problem is that you are calling os.Create. The documentation for os.Create says
> Create creates the named file with mode 0666 (before umask), truncating it if it already exists. If successful, methods on the returned File can be used for I/O; the associated file descriptor has mode O_RDWR. If there is an error, it will be of type *PathError.
So each call to os.Create will remove all content from the file you passed. Instead what you want is probably os.OpenFile with the os.O_CREATE, os.O_WRONLY and os.O_APPEND flags. This will make sure that the file will be created, if it doesn't exists, but won't truncate it.
But there is another problem in your code. You are calling defer csvfile.Close()
inside the loop. A deferred function will only be executed once the function returns and not after the loop iteration. This can lead to problems, especially since you are opening the same file over and over again.
Instead you should open the file once before the loop so that you only need to close it once. Like this:
package main
import (
"encoding/csv"
"fmt"
"net/http"
"os"
)
func PageRequest(w http.ResponseWriter, r *http.Request) {
// Default page number is 1
if len(r.URL.Path) <= 1 {
r.URL.Path = "/1"
}
// Page number is not negative or 0
page.Abs(page)
if page.Cmp(one) == -1 {
page.SetInt64(1)
}
// Page header
fmt.Fprintf(w, PageHeader, pages, previous, next)
// Save in csv
csvfile, err := os.OpenFile("marks.csv", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
if err != nil {
fmt.Println("Error:", err)
return
}
defer csvfile.Close()
writer := csv.NewWriter(csvfile)
defer writer.Flush()
// Marks for UID
UID, length := compute(start)
for i := 0; i < length; i++ {
key := UID[i]
fmt.Fprintf(w, key.fname, key.marks, key.lname, key.remarks)
records := [][]string{{key.fname, key.marks, key.lname, key.remarks}}
for _, record := range records {
err := writer.Write(record)
if err != nil {
fmt.Println("Error:", err)
return
}
}
}
// Page Footer
fmt.Fprintf(w, PageFooter, previous, next)
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论