Go 学习笔记(三十六)数据存储 (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 PostsByAuthor map[string][]*Post

还可以关键字来检索 Content 从而找出关键字近似的文章,也就是搜索引擎类型的检索方式。这个比较复杂一些。

还有一些文章设置了标签关键字,比如 linux 类的文章,docker 标签的文章,shell 标签的文章等。为了可以使用标签检索文章,还需要创建一个按照标签方式进行存储文章的 map 容器。关于标签的存储方式,此处略过。

现在假设就前面定义的两种存储方式:PostById 和 PostsByAuthor,定义提交文章的函数:

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

注意,上面 store() 函数的参数是指针类型的。

文章存储到上面两种容器中后,就可以从任意一种容器中检索文章。因为存储时是使用指针类型存储的,所以无论从哪一种容器中检索得到的文章,和另一种方式检索得到的是相同的文章。

例如:

// 按文章Id检索文章并输出文章的Content
fmt.Println(PostById[1])
fmt.Println(PostById[2])

// 按作者检索文章并输出文章的Content
for _, post := range PostsByAuthor["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)
	}
}

执行结果:

&{1 Hello 1 userA}
&{2 Hello 2 userB}
&{1 Hello 1 userA}
&{4 Hello 4 userA}
&{3 Hello 3 userC}

上一篇 Go 学习笔记(三十五)Cookie
Go 学习笔记(目录)
下一篇 Go 学习笔记(三十七)数据存储 (2)——CSV 文件