问题内容
我需要请求、处理数据并将其格式化为 csv,然后根据请求通过 web 服务发送它们。
假设请求和处理的数据位于下面的 data
中,我设法使用中间临时文件来做到这一点:
package main import ( "encoding/csv" "io/ioutil" "net/http" "os" "strconv" "github.com/go-chi/chi/v5" ) type data struct { name string age int } func main() { data := []data{ {"john", 30}, {"jane", 20}, } tempfilename := "temp.csv" // create temporary intermediate file file, err := os.create(tempfilename) defer file.close() if err != nil { panic(err) } w := csv.newwriter(file) var csvdata [][]string for _, record := range data { row := []string{record.name, strconv.itoa(record.age)} csvdata = append(csvdata, row) } w.writeall(csvdata) // read temporary intermediate file to send it via http filebytes, err := ioutil.readfile(tempfilename) if err != nil { panic(err) } // send the file on request router := chi.newrouter() router.get("/data", func(w http.responsewriter, r *http.request) { w.header().set("content-type", "application/octet-stream") w.writeheader(http.statusok) w.write(filebytes) }) http.listenandserve(":8087", router) }
请求成功:
PS C:temp> wget http://localhost:8087/data --2023-06-13 15:34:00-- http://localhost:8087/data Resolving localhost (localhost)... ::1, 127.0.0.1 Connecting to localhost (localhost)|::1|:8087... connected. HTTP request sent, awaiting response... 200 OK Length: 16 [application/octet-stream] Saving to: 'data' data 100%[=================================================>] 16 --.-KB/s in 0s 2023-06-13 15:34:00 (523 KB/s) - 'data' saved [16/16] PS C:temp> cat data John,30 Jane,20
到目前为止一切顺利 – 现在我想通过
删除中间文件
- 使用内存“容器”来写入 csv 数据
- 将其内容以字节形式写入 http 编写器
我还是不太明白如何使用io.*
和bufio.*
来登陆所需的类型:
csv.newwriter()
需要*os.file
并返回*csv.writer
- 这个
*csv.writer
内容需要以某种方式提取为byte
… - …为了提供
http.responsewriter.write()
解决不同类型的内存文件操作问题的一般机制(以及特定于本例的机制)是什么?
正确答案
csv.newwriter
采用 io.writer
,因此您可以将 http.responsewriter
的实例传递给它,而无需将内容写入文件或内存。
这是演示:
package main import ( "encoding/csv" "fmt" "net/http" "strconv" "github.com/go-chi/chi/v5" ) type Data struct { Name string Age int } func main() { router := chi.NewRouter() router.Get("/data", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/octet-stream") w.WriteHeader(http.StatusOK) data := []Data{ {"John", 30}, {"Jane", 20}, } csvWriter := csv.NewWriter(w) var csvData [][]string for _, record := range data { row := []string{record.Name, strconv.Itoa(record.Age)} csvData = append(csvData, row) } if err := csvWriter.WriteAll(csvData); err != nil { // handle the error fmt.Println(err) } }) http.ListenAndServe(":8087", router) }