使用GO语言以CSV格式写入/保存数据

时间:2017-06-10 13:25:04

标签: go

我正在尝试将学生成绩写入GO中的csv文件。

它使用Println每页打印所需的10个结果,但仅保存csv中的最后一个值(不是全部10个)。

这就是我正在做的事情

  1. 访客访问studentmarks.com/page=1 显示10名学生的标记,并以CSV格式保存

  2. 访问者点击下一页,导航到studentmarks.com/page=2 将显示另外10名学生的标记,并将其保存在CSV

  3. 中的后续列/行中

    等等

    fmt.Fprintf(w, KeyTemplate, key.fname, key.marks, key.lname )工作正常并且每页显示所有10个结果,但我无法将所有10个结果保存在CSV中(使用我当前的代码,只保存最后的结果)。

    以下是我的代码片段,负责打印和保存结果。

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

    如何使用go语言打印并保存(在csv中)所有10个结果?

1 个答案:

答案 0 :(得分:0)

基本问题是您正在呼叫os.Createos.Create的文档说

  

Create使用模式0666(在umask之前)创建命名文件,如果已经存在则将其截断。如果成功,返回的文件上的方法可用于I / O;关联的文件描述符具有模式O_RDWR。如果有错误,则其类型为* PathError。

因此,每次调用os.Create都会删除您传递的文件中的所有内容。相反,你想要的os.OpenFileos.O_CREATEos.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) {
    // 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)
}