GO语言工程实践课后作业 | 青训营

GO语言工程实践课后作业 | 青训营

这是我在字节跳动青训营学习的第7天,也是我参加《第六届青训营笔记伴读》的第三篇笔记

需求描述

  • 发布话题和回帖

  • 本地ID生成需要保证不重复,唯一性

  • Append文件,更新索引

框架(Gin)

官方介绍

Gin 是一个用 Go (Golang) 编写的 HTTP web 框架。 它是一个类似于 martini 但拥有更好性能的 API 框架, 优于 httprouter,速度提高了近 40 倍。如果你需要极好的性能,使用 Gin 吧。

引入Gin框架

1.下载并安装 gin:

shell 复制代码
$ go get -u github.com/gin-gonic/gin

2.将 gin 引入到代码中:

arduino 复制代码
import "github.com/gin-gonic/gin"

源码介绍

本项目相关代码已上传至github message_board

目录结构

controller视图层

主要负责处理用户输入的数据,并相应相应数据,包含两个文件

  • publish.go

    用户发布数据的接口,包括发布话题,以及回复

  • query_page_info.go

    用户查看数据的接口,可查看话题和对应的回复

data数据库

存储数据的文件,因为只是一个简单的项目,所以并没有用到数据库,而是使用文件存储json格式的文件,包含两个文件

  • post : 所有回复的信息
  • topic :所有话题的信息

repository 数据层

负责数据库的增删改查,为上层提供了简单易用的接口,包含三个文件

  • db_init.go 从文件中读取出所有的数据,并存储到对应的Map中,便于后续的查找
  • post.go
    • 实现了通过话题id查找对应回复
    • 实现了新增回复
    • 实现了查找id的最大值(用于实现唯一id)
  • topic.go
    • 实现了通过id查找对应话题
    • 实现了新增话题
    • 实现了查找id的最大值(用于实现唯一id)

service

处理业务逻辑,对数据层的数据进行处理,并将结果返回给视图层,只包含一个文件

  • query_page_info.go : 查找话题及相应回复

server.go

  • 程序入口,定义路由,处理路由,调用接口响应请求;

功能实现

实现思路

1.获取数据

发布话题首先要获取用户要发布的内容,包括标题和内容,如果是回复的话,需要有回复话题的id还有内容,我在设置路由时,获取到了用户的输入,校验完数据后传给controller进行处理

2.处理数据

获取完数据后,需要对数据进行封装处理,使其成为一个结构体,需要给它设置一个id,还有时间戳, 时间戳可以通过time.now.Unix()获取

3.获取唯一id

我的实现思路是,找到所有id中的最大值,然后加一,

4.保存数据

将结构体序列化为JSON格式,追加到文件末尾,同时更新索引

  • 若是发表话题,直接新增索引就可以
  • 若是发表回复,需要先判断,当前话题有没有回复,没有的话需要新创建一个数组

具体实现

server.go定义了两个路由,一个是发布话题/commuity/page/publish/topic,一个是发表回复/commuity/page/publish/topic,两个都是post方法,因为没有实现前端,所以这里使用postman进行接口测试,这两个路由主要是接受用户输入的信息,然后交给controller处理,这里涉及到gin获取post参数的方式

我认为,用户发表话题前端大概率是表单方式提交,所以这里默认请求参数为Form表单,使用PostForm方法可以获取对应参数,方法参数为表单控件的名称

此处参考了掘金的一篇文章Gin框架获取请求参数的各种方式详解

go 复制代码
r.POST("/community/page/publish/topic", func(context *gin.Context) {  
  
title := context.PostForm("title")  
content := context.PostForm("content")  
  
data, err2 := cotroller.PublishTopic(title, content)  
if err2 != nil {  
return  
}  
  
context.JSON(200, data)  
})

获取到用户的数据后,我们要对其进行封装,首先要找到id的最大值,在读文件时,我们将所有话题的信息存储到了topicIndexMap中,这是一个map的数据结构,key为id,value为话题信息的结构体Topic 遍历所有的key,找到最大值,再加一就是我们新插入值的id

go 复制代码
func (*TopicDao) FindMaxId() int64 {  
id := int64(math.MinInt64)  
    for k, _ := range topicIndexMap {  
        if k > id {  
        id = k  
        }  
    }  
return id  
}

若是发表回复的话,由于postIndexMap是一个树形的结构,不方便我们查找最大值,所以从文件读取数据时,我们将所有回复信息都保存到了一个数组中,然后再遍历数组构造Map,有了这个数组,就可以很简单的实现查找最大值

有了id后,就可以对用户输入的信息进行封装了,由于逻辑比较简单,我们直接在controller层实现了,

go 复制代码
func PublishTopic(title string, content string) (topic repository.Topic, err error) {  
  
id := repository.NewTopicDaoInstance().FindMaxId() + 1  
time := time.Now().Unix()  
topic, err = repository.NewTopicDaoInstance().CreateTopic(id, title, content, time)  
if err != nil {  
    return topic, err  
}  
return topic, nil  
}

数据封装好需要存储到文件中,并更新索引

封装数据

go 复制代码
    newTopic := Topic{  
    Id: id,  
    Title: title,  
    Content: content,  
    CreateTime: createTime,  
}  

更新索引

go 复制代码
topicIndexMap[newTopic.Id] = &newTopic  

保存到文件

go 复制代码
f, err := os.OpenFile("./data/topic", os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600)  //打开文件
if err != nil {  
    return newTopic, err  
}  
defer f.Close()  //在函数执行完之后关闭文件
marshal, _ := json.Marshal(newTopic)  //序列化
if _, err = f.WriteString(string(marshal) + "\n"); err != nil {  //写入文件
    return newTopic, err  
}  

保存文件时,由于默认每条数据后会换行,会导致下次读数据时读到空行报错Initunexpected end of JSON input,因此在读文件时,我们需要加一个判断,若当前行为空字符串"",直接结束文件读取

总结

麻雀虽小但五脏俱全,学到的东西也很多,对go语言的熟练度++,跟java中springboot相似,甚至更简单,但对于并发,还是不太懂,并不知道哪里会有map的并发安全问题(我好像就没用到并发)

参考

相关推荐
夭要7夜宵2 天前
Go 垃圾回收 | 豆包MarsCode AI刷题
青训营笔记
末班车4223 天前
前端框架中的设计模式 | 豆包MarsCode AI刷题
青训营笔记
VanceLLF4 天前
神奇数字组合 | 豆包MarsCode AI刷题
青训营笔记
lann4 天前
Go 程序的优化 | 豆包MarsCode AI刷题
青训营笔记
用户52281271049784 天前
性能优化与调试技巧 | 豆包MarsCode AI刷题
青训营笔记
千慌百风定乾坤6 天前
Go 语言入门指南:基础语法和常用特性解析(下) | 豆包MarsCode AI刷题
青训营笔记
FOFO6 天前
青训营笔记 | HTML语义化的案例分析: 粗略地手绘分析juejin.cn首页 | 豆包MarsCode AI 刷题
青训营笔记
滑滑滑8 天前
后端实践-优化一个已有的 Go 程序提高其性能 | 豆包MarsCode AI刷题
青训营笔记
柠檬柠檬8 天前
Go 语言入门指南:基础语法和常用特性解析 | 豆包MarsCode AI刷题
青训营笔记
用户967136399658 天前
计算最小步长丨豆包MarsCodeAI刷题
青训营笔记