设为首页 加入收藏

TOP

Go Web:数据存储(2)——CSV文件(一)
2018-12-03 20:11:18 】 浏览:264
Tags:Web 数据 存储 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][]*
首页 上一页 1 2 下一页 尾页 1/2/2
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇104 - kube-scheduler源码分析 - .. 下一篇Go Web:数据存储(1)——内存存储

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目