数据存储
存储在内存中
package main
import "fmt"
type Post struct {
Id int
Content string
Author string
/*
程序会使用Post struct来表示应用中的帖子,并把结构存在内存中
Post struct最主要的数据是帖子的内容,用户也可以通过唯一ID或者Author获取帖子。
程序会通过讲一个代表帖子的键映射到实际的Post结构来存储多个帖子,
*/
}
// 为了提供两种不同的方法来方法来方位帖子, 程序分别使用了两个map来创建不同的map
/*
程序使用两个变量来存储map,PostById将帖子的唯一Id映射值指向帖子的指针;
PostByAuthor将通过作者名字映射到一个slice, 不管是PostById 还是PostByAuthor ,
他们映射的都是指向帖子的指针而不是帖子本身; 这样做可以确保程序无论是通过Id还是通过作者的名字来获取帖子
得到的都是相同的帖子,而不是帖子的副本
*/
var PostById map[int]*Post
var PostByAuthor map[string][]*Post
func store(post Post) {
PostById[post.Id] = &post
PostByAuthor[post.Author] = append(PostByAuthor[post.Author], &post)
/*
store函数会将一个指向帖子的指针分别存到PostById变量和PostByAuthor变量里
*/
}
func main() {
PostById = make(map[int]*Post)
PostByAuthor = make(map[string][]*Post)
post1 := Post{Id: 1, Content: "hello world by 张三.", Author: "张三"}
post2 := Post{Id: 2, Content: "hello world by 李四.", Author: "李四"}
post3 := Post{Id: 3, Content: "hello world by 王五.", Author: "王五"}
post4 := Post{Id: 4, Content: "hello world by xxxx.", Author: "xxxx"}
store(post1)
store(post2)
store(post3)
store(post4)
fmt.Println(PostById[1])
fmt.Println(PostById[2])
for _, post := range PostByAuthor["张三"] {
fmt.Println(post)
}
}
读写文件
package main
import (
"fmt"
"io/ioutil"
"os"
)
func main() {
data := []byte("Hello World!
")
// ----------------- ioutil.WriteFile ReadFile 读写文件 ----------------------
err := ioutil.WriteFile("data1", data, 0644)
if err != nil {
panic(err)
}
// ReadFile WriteFile函数对文件进行读取和写入
read1, _ := ioutil.ReadFile("data1")
fmt.Println(string(read1))
/*
ioutil.WriteFile 需要文件名 写入的数据 设置文件的权限
ioutil.ReadFile 只需要传入文件名即可
无论是传递给WriteFile的数据,还是ReadFile返回的数据,都是由一个字节组成的切片
*/
// 通过File 结构对文件进行读取和写入
file1, _ := os.Create("data2")
defer file1.Close()
bytes, _ := file1.Write(data)
fmt.Printf("写入数据 %d bytes to file
", bytes)
// -------------------------- File 读写文件 ---------------------------------
file2, _ := os.Open("data2")
defer file2.Close()
// defer 语句可以将给定的函数第阿勇推到一个占里,保存在栈中调用会在函数返回后执行
read2 := make([]byte, len(data))
bytes, _ = file2.Read(read2)
fmt.Printf("读取数据 %d bytes to file
", bytes)
fmt.Println(string(bytes))
}
CSV
package main
import (
"encoding/csv"
"fmt"
"os"
"strconv"
)
type Post struct {
Id int
Content string
Author string
}
func main() {
// -------------------- 写 ---------------
// 创建一个csv文件
csv_file, err := os.Create("posts.csv")
if err != nil {
panic(err)
}
defer csv_file.Close()
allPosts := []Post{
Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"},
Post{Id: 2, Content: "Bonjour Monde!", Author: "Pierre"},
Post{Id: 3, Content: "Hola Mundo!", Author: "Pedro"},
Post{Id: 4, Content: "Greetings Earthlings!", Author: "Sau Sheong"},
}
writer := csv.NewWriter(csv_file)
for _, post := range allPosts {
line := []string{strconv.Itoa(post.Id), post.Content, post.Author}
err := writer.Write(line)
if err != nil {
panic(err)
}
}
writer.Flush()
// -------------------- 读 ------------
// 打开csv文件
file, err := os.Open("posts.csv")
if err != nil {
panic(err)
}
defer file.Close()
// 读取
reader := csv.NewReader(file)
// 即使读取器在读取发现记录(record) 里缺少某些字段时,go会抛出错误,如果设置为负数就不会
reader.FieldsPerRecord = -1
record, err := reader.ReadAll()
if err != nil {
panic(err)
}
var posts []Post
for _, item := range record {
id, _ := strconv.ParseInt(item[0], 0, 0)
post := Post{Id: int(id), Content: item[1], Author: item[2]}
posts = append(posts, post)
}
fmt.Println(posts[0].Id)
fmt.Println(posts[0].Content)
fmt.Println(posts[0].Author)
}
gob 二进制文件
package main
import (
"bytes"
"encoding/gob"
"fmt"
"io/ioutil"
)
type Post struct {
Id int
Content string
Author string
}
func store(data interface{}, filename string) {
/*
第一个参数是空接口, 第二是文件名(二进制文件名)
*/
// bytes.Buffer 这个实际上就是拥有一个Read和Write方法的可变长度(variable-sized)字节缓冲区,
// bytes.Buffer即是读取器也是写入器
buffer := new(bytes.Buffer)
// store函数会把缓冲区传递给NewEncoder函数,一次来创建出gob编码器,
encoder := gob.NewEncoder(buffer)
// 调用解码器Encode方法将数据(Post struct)编码到缓冲区里,
err := encoder.Encode(data)
if err != nil {
panic(err)
}
// 最后再将缓冲区中已编码的数据写入文件
err = ioutil.WriteFile(filename, buffer.Bytes(), 0600)
if err != nil {
panic(err)
}
}
func load(data interface{}, filename string) {
raw, err := ioutil.ReadFile(filename)
if err != nil {
panic(err)
}
buffer := bytes.NewBuffer(raw)
dec := gob.NewDecoder(buffer)
err = dec.Decode(data)
if err != nil {
panic(err)
}
}
func main() {
post := Post{Id: 1, Content: "Hello World!", Author: "Sau Sheong"}
store(post, "post1")
var postRead Post
load(&postRead, "post1")
fmt.Println(postRead)
}