本文接上一篇:内存存储。html
关于CSV文件的说明,见csv文件格式app
当数据存储到了内存中,能够在须要的时候持久化保存到磁盘文件中。好比保存为csv格式的文件,下一篇再介绍序列化持久到文件中。函数
下面是持久化到csv文件的函数代码:post
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文件的内容:code
2,Hello 2,userB 3,Hello 3,userC 4,Hello 4,userA 1,Hello 1,userA
数据保存到了csv文件,天然须要从csv文件中读取数据到内存。如下是读取csv文件的函数:htm
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
:blog
这个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}