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

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

  1. Visitor visits studentmarks.com/page=1 Marks for 10 students are displayed and it is also saved in CSV

  2. 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?

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