本文接上一篇:內存存儲。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}