在上篇教程中,学院君给大家演示了如何通过 JSON 编码存储文本数据到磁盘文件,除此之外,Go 语言还提供了对 CSV 格式文件的支持,CSV 文件本质上虽然就是文本格式数据,不过可以兼容 Excel 表格,这样一来就可以极大方便我们对大批量数据进行管理。
使用 encoding/csv 包读写 CSV 文件
encoding/csvcsv.go
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
)
type Tutorial struct {
Id int
Title string
Summary string
Author string
}
func main() {
// 创建一个 tutorials.csv 文件
csvFile, err := os.Create("tutorials.csv")
if err != nil {
panic(err)
}
defer csvFile.Close()
// 初始化字典数据
tutorials := []Tutorial{
Tutorial{Id: 1, Title: "Go 入门编程", Summary: "Go 基本语法和使用示例", Author: "学院君"},
Tutorial{Id: 2, Title: "Go Web 编程", Summary: "Go Web 编程入门指南", Author: "学院君"},
Tutorial{Id: 3, Title: "Go 并发编程", Summary: "通过并发编程提升性能", Author: "学院君"},
Tutorial{Id: 4, Title: "Go 微服务开发", Summary: "基于 go-micro 框架开发微服务", Author: "学院君"},
}
// 初始化一个 csv writer,并通过这个 writer 写入数据到 csv 文件
writer := csv.NewWriter(csvFile)
for _, tutorial := range tutorials {
line := []string{
strconv.Itoa(tutorial.Id), // 将 int 类型数据转化为字符串
tutorial.Title,
tutorial.Summary,
tutorial.Author,
}
// 将切片类型行数据写入 csv 文件
err := writer.Write(line)
if err != nil {
panic(err)
}
}
// 将 writer 缓冲中的数据都推送到 csv 文件,至此就完成了数据写入到 csv 文件
writer.Flush()
// 打开这个 csv 文件
file, err := os.Open("tutorials.csv")
if err != nil {
panic(err)
}
defer file.Close()
// 初始化一个 csv reader,并通过这个 reader 从 csv 文件读取数据
reader := csv.NewReader(file)
// 设置返回记录中每行数据期望的字段数,-1 表示返回所有字段
reader.FieldsPerRecord = -1
// 通过 readAll 方法返回 csv 文件中的所有内容
record, err := reader.ReadAll()
if err != nil {
panic(err)
}
// 遍历从 csv 文件中读取的所有内容,并将其追加到 tutorials2 切片中
var tutorials2 []Tutorial
for _, item := range record {
id, _ := strconv.ParseInt(item[0], 0, 0)
tutorial := Tutorial{Id: int(id), Title: item[1], Summary: item[2], Author: item[3]}
tutorials2 = append(tutorials, tutorial)
}
// 打印 tutorials2 的第一个元素验证 csv 文件写入/读取是否成功
fmt.Println(tutorials2[0].Id)
fmt.Println(tutorials2[0].Title)
fmt.Println(tutorials2[0].Summary)
fmt.Println(tutorials2[0].Author)
}
可以看到新建文件、打开文件、关闭文件和上篇教程操作普通的磁盘文件并无区别,不过这里为了支持通过 CSV 格式写入和读取文件,我们在文件句柄之上套了一层 CSV Writer 和 CSV Reader,这有点像适配器模式,然后我们就可以通过 CSV Writer 写入数据到 CSV 文件,通 过 CSV Reader 读取 CSV 文件了:
...
// 初始化一个 csv writer,并通过这个 writer 写入数据到 csv 文件
writer := csv.NewWriter(csvFile)
...
// 初始化一个 csv reader,并通过这个 reader 从 csv 文件读取数据
reader := csv.NewReader(file)
...
encoding
使用方法了操作 CSV 文件一致,这也是 Go 语言设计之美的体现,通过接口与组合的方式可以很方便的构建起复杂的业务功能,感兴趣的同学可以去看下 Go 官方的 io 包实现源码。
osioutilioutil
关于上述代码的实现细节,都已经通过详细的注释标注了,我们重点关注如何将数据写入 CSV 文件,以及如何从 CSV 文件读取数据即可。
运行上述代码,返回结果如下,说明 CSV 文件写入和读取成功:
当然,你也可以在此基础上扩展出 CSV 文件数据的增删改查功能,感兴趣的同学可以自己尝试下,这里就具体展开了。
使用不同软件预览 CSV 文件
csv.gotutorials.csv
在 Mac 系统中,你可以通过 Numbers 应用打开这个文件进行预览,格式化后的数据就好看多了:
在 Windows 中,可以通过 Excel 软件打开这个文件,但是现在看到的是乱码数据:
这是因为 Excel 默认并不是 UTF-8 编码,因此要解决这个乱码问题,可以在对应的 CSV 文件写入 UTF-8 BOM 头,告知 Excel 通过 UTF-8 编码打开这个文件:
...
// 写入 UTF-8 BOM,防止中文乱码
csvFile.WriteString("\xEF\xBB\xBF")
// 初始化一个 csv writer,并通过这个 writer 写入数据到 csv 文件
writer := csv.NewWriter(csvFile)
...
tutorials.csv
关于 Excel 文件的读取和写入,学院君就简单介绍到这里,这里留一个课后作业,参考 encoding/csv 包读写 CSV 文件的方式,试着编写一段使用 encoding/json 包读写 JSON 文件的代码并正常运行起来,看看生成的文件是否符合预期。