<>

存储到CSV文件中

* 1.内存存储 <https://www.cnblogs.com/f-ck-need-u/p/10054073.html>

* 2.CSV文件存储 <https://www.cnblogs.com/f-ck-need-u/p/10060242.html>

* 3.gob序列化存储 <https://www.cnblogs.com/f-ck-need-u/p/10060245.html>
本文接上一篇:内存存储 <https://www.cnblogs.com/f-ck-need-u/p/10054073.html>。

关于CSV文件的说明,见csv文件格式 <https://www.cnblogs.com/f-ck-need-u/p/10054553.html>

当数据存储到了内存中,可以在需要的时候持久化保存到磁盘文件中。比如保存为csv格式的文件,下一篇再介绍序列化持久到文件中。

下面是持久化到csv文件的函数代码:
func storeToCsv(filename string, posts map[int]*Post) { // 创建文件 csvFile, err
:= os.Create(filename) if err != nil { panic(err) } defer csvFile.Close() //
获取csv的Writer writer := csv.NewWriter(csvFile) //
将map中的Post转换成slice,因为csv的Write需要slice参数 // 并写入csv文件 for _, post := range posts
{ record := []string{strconv.Itoa(post.Id), post.Content, post.Author} err1 :=
writer.Write(record) if err1 != nil { panic(err1) } } // 确保所有内存数据刷到csv文件
writer.Flush() }
这个函数的逻辑很简单,无需过多的解释。需要注意的是,os.Create()函数在文件存在时会截断文件,如有需要,可以考虑使用追加写入的相关函数。

当需要将保存在内存中的post保存到csv文件时,只需调用该函数,传递一个文件名以及PostById作为参数即可:
storeToCsv("d:/a.csv", PostById)
保存之后,以下是a.csv文件的内容:
2,Hello 2,userB 3,Hello 3,userC 4,Hello 4,userA 1,Hello 1,userA
数据保存到了csv文件,自然需要从csv文件中读取数据到内存。以下是读取csv文件的函数:
func load(filename string) []*Post { // 打开文件 file, err := os.Open(filename) if
err != nil { panic(err) } defer file.Close() // 获取csv的reader reader :=
csv.NewReader(file) // 设置FieldsPerRecord为-1 reader.FieldsPerRecord = -1 //
读取文件中所有行保存到slice中 records, err := reader.ReadAll() if err != nil { panic(err) }
var posts []*Post // 将每一行数据保存到内存slice中 for _, item := range records { id, _ :=
strconv.Atoi(item[0]) post := &Post{Id: id, Content: item[1], Author: item[2]}
posts = append(posts, post) } return posts }
逻辑也很简单,唯一需要注意的是FiledsPerRecord=-1:

* 设置为负数表示读取时每条记录的字段数量可以随意

* 如果设置为正数N,则表示每条记录必须且只读取N个字段,如果字段少于N,则报错
* 如果设置为0,则表示按照第一条记录所拥有的字段数量进行读取剩余记录,也就是说每一条记录的字段数量都必须和第一条记录相同
这个load()函数返回一个slice,这个slice中保存了所有读取到的文章指针。
s := load("d:/a.csv")
因为使用var PostById map[int]*Post和var PostsByAuthor map[string][]*Post
保存一篇篇的文章,迭代此slice即可将slice中的post保存到这两个map中。
for _, post := range s { store(post) }
然后就可以从这两个map中按照Id或者按照Author进行检索:
fmt.Println(PostById[1]) fmt.Println(PostById[2]) for _, post := range
PostsByAuthor["userA"] { fmt.Println(post) }
下面是完整的保存到csv文件以及读取csv文件的代码:
package main import ( "encoding/csv" "fmt" "os" "strconv" ) type Post struct {
Id int Content string Author string } var PostById map[int]*Post var
PostsByAuthor map[string][]*Post func store(post *Post) { PostById[post.Id] =
post PostsByAuthor[post.Author] = append(PostsByAuthor[post.Author], post) }
func storeToCsv(filename string, posts map[int]*Post) { csvFile, err :=
os.Create(filename) if err != nil { panic(err) } defer csvFile.Close() writer
:= csv.NewWriter(csvFile) for _, post := range posts { record :=
[]string{strconv.Itoa(post.Id), post.Content, post.Author} err1 :=
writer.Write(record) if err1 != nil { panic(err1) } } writer.Flush() } func
load(filename string) []*Post { file, err := os.Open(filename) if err != nil {
panic(err) } defer file.Close() reader := csv.NewReader(file)
reader.FieldsPerRecord = -1 records, err := reader.ReadAll() if err != nil {
panic(err) } var posts []*Post for _, item := range records { id, _ :=
strconv.Atoi(item[0]) post := &Post{Id: id, Content: item[1], Author: item[2]}
posts = append(posts, post) } return posts } func main() { PostById =
make(map[int]*Post) PostsByAuthor = make(map[string][]*Post) // 模拟几篇文章 post1 :=
&Post{Id: 1, Content: "Hello 1", Author: "userA"} post2 := &Post{Id: 2,
Content: "Hello 2", Author: "userB"} post3 := &Post{Id: 3, Content: "Hello 3",
Author: "userC"} post4 := &Post{Id: 4, Content: "Hello 4", Author: "userA"} //
存储到内存中 store(post1) store(post2) store(post3) store(post4) //
将内存中的map容器,保存到csv文件中 storeToCsv("d:/a.csv", PostById) // 为了测试,此处将已保存在内存中的数据清空
PostById = map[int]*Post{} PostsByAuthor = map[string][]*Post{} // 下面是加载csv文件 s
:= load("d:/a.csv") for _, post := range s { store(post) } // 检索
fmt.Println(PostById[1]) fmt.Println(PostById[2]) for _, post := range
PostsByAuthor["userA"] { fmt.Println(post) } for _, post := range
PostsByAuthor["userC"] { fmt.Println(post) } }
运行结果:
&{1 Hello 1 userA} &{2 Hello 2 userB} &{1 Hello 1 userA} &{4 Hello 4 userA}
&{3 Hello 3 userC}

友情链接
KaDraw流程图
API参考文档
OK工具箱
云服务器优惠
阿里云优惠券
腾讯云优惠券
华为云优惠券
站点信息
问题反馈
邮箱:ixiaoyang8@qq.com
QQ群:637538335
关注微信