欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

Go Web:数据存储(2)——CSV文件

程序员文章站 2023-10-15 15:20:32
存储到CSV文件中 "1.内存存储" "2.CSV文件存储" "3.gob序列化存储" 本文接上一篇: "内存存储" 。 关于CSV文件的说明,见 "csv文件格式" 当数据存储到了内存中,可以在需要的时候持久化保存到磁盘文件中。比如保存为csv格式的文件,下一篇再介绍序列化持久到文件中。 下面是持 ......

存储到csv文件中

本文接上一篇:。

关于csv文件的说明,见

当数据存储到了内存中,可以在需要的时候持久化保存到磁盘文件中。比如保存为csv格式的文件,下一篇再介绍序列化持久到文件中。

下面是持久化到csv文件的函数代码:

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文件的内容:

2,hello 2,userb
3,hello 3,userc
4,hello 4,usera
1,hello 1,usera

数据保存到了csv文件,自然需要从csv文件中读取数据到内存。以下是读取csv文件的函数:

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

  • 设置为负数表示读取时每条记录的字段数量可以随意
  • 如果设置为正数n,则表示每条记录必须且只读取n个字段,如果字段少于n,则报错
  • 如果设置为0,则表示按照第一条记录所拥有的字段数量进行读取剩余记录,也就是说每一条记录的字段数量都必须和第一条记录相同

这个load()函数返回一个slice,这个slice中保存了所有读取到的文章指针。

s := load("d:/a.csv")

因为使用var postbyid map[int]*postvar 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}