1. 程式人生 > >Go Web:資料儲存(1)——記憶體儲存

Go Web:資料儲存(1)——記憶體儲存

資料可以儲存在記憶體中、檔案中、按二進位制序列化儲存的檔案中、資料庫中等。

記憶體儲存

將資料儲存到記憶體中。此處所指的記憶體是指應用程式自身的記憶體空間(如slice、array、map、struct、佇列、樹等等容器),而不是外部的記憶體資料庫(如redis)。

例如,要儲存部落格文章。

每篇部落格文章都有文章ID、文章內容以及文章作者。假設它是一個struct結構:

type Post struct {
    Id      int
    Content string
    Author  string
}

為了在記憶體中儲存每一篇Post,可以考慮將每篇Post放進一個slice,也可以放進map。因為id或author或content和文章之間有對映關係,使用map顯然更好一些。

var PostById map[int]*Post

這樣就能通過Id來檢索對應的文章,注意上面map的value是指標型別的,不建議使用值型別的,這樣會產生副本。

如果想要通過Author來檢索文章,則還可以使用一個map來儲存這個作者下的所有文章。因為一個作者可以有多篇文章,所以map的value應該是一個容器,比如slice。

var PostByAuthor map[string][]*Post

還可以關鍵字來檢索Content從而找出關鍵字近似的文章,也就是搜尋引擎型別的檢索方式。這個比較複雜一些。

還有一些文章設定了標籤關鍵字,比如linux類的文章,docker標籤的文章,shell標籤的文章等。為了可以使用標籤檢索文章,還需要建立一個按照標籤方式進行儲存文章的map容器。關於標籤的儲存方式,此處略過。

現在假設就前面定義的兩種儲存方式:PostById和PostByAuthor,定義提交文章的函式:

func store(post *Post) {
    PostById[post.Id] = post
    PostByAuthor[post.Author] = append(PostByAutor[post.Autor], post)
}

注意,上面store()函式的引數是指標型別的。

文章儲存到上面兩種容器中後,就可以從任意一種容器中檢索文章。因為儲存時是使用指標型別儲存的,所以無論從哪一種容器中檢索得到的文章,和另一種方式檢索得到的是相同的文章。

例如:

// 按文章Id檢索文章並輸出文章的Content
fmt.Println(PostById[1])
fmt.Println(PostById[2])

// 按作者檢索文章並輸出文章的Content
for _, post := range PostByAuthor["userA"]{
    fmt.Println(post)
}

下面是完整的程式碼:

package main

import (
    "fmt"
)

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 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)
    fmt.Println(PostById[1])
    fmt.Println(PostById[2])
    for _, post := range PostsByAuthor["userA"] {
        fmt.Println(post)
    }
    for _, post := range PostsByAuthor["userC"] {
        fmt.Println(post)
    }
}