青训营X豆包MarsCode 技术训练营之简易发帖项目记录 | 豆包MarsCode AI 刷题

54 阅读5分钟

​ 首先就是这次文章是怎么来的,是因为在训练营中看到了第四课,讲的是Go语言工程实践以及对应使用的gin框架,但是发现项目全套代码是有了,但是却没有分段的对应代码,应该是后边课程讲的但是没在此次训练营的课程表中吗,所以在此也是根据自己的理解对该项目进行一定的记录学习。并且,由于是直接对于一个项目进行分析的,就不过多对于理论部分进行讲解了。

1、Gin框架。

​ gin框架也是go中的一个最常见的框架了,能够让我们快速的启动一些http服务,非常的方便快捷。这里也就不多介绍了,本篇文章的侧重点是项目分析,这个也不是很难,可以直接看官方文档即可。gin-gonic.com/zh-cn/docs/…

2、项目结构

首先就是我们可以去分析一下项目的结果,这里我将给的项目中的一些测试以及知识点代码都去掉了,剩下了这些代码,并且其中service是用来测试项目功能的

image.png

接下来我们就是对这些代码进行理解。

首先就是启动项,server.go

	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})

	r.GET("/community/page/get/:id", func(c *gin.Context) {
		topicId := c.Param("id")
		data := handler.QueryPageInfo(topicId)
		c.JSON(200, data)
	})

	r.POST("/community/post/do", func(c *gin.Context) {
		uid, _ := c.GetPostForm("uid")
		topicId, _ := c.GetPostForm("topic_id")
		content, _ := c.GetPostForm("content")
		data := handler.PublishPost(uid, topicId, content)
		c.JSON(200, data)
	})

我们就是可以发现这是一个很简单的启动服务

定义了三个路由,分别是一个测试路由,一个获取页面,一个添加页面的路由,没有什么很难理解的,Init则是初始化各组件,并且如果初始化失败则会返回err

接下来我们去看看util,发现里面只有一个文件,看名字就很浅显易懂

看看代码就发现是创建一个日志记录器方便使用,以方便调试

然后就是看repository,这个名字也很明显,仓库对吧,这也就是和数据库打交道的地方,专门用于操作数据库的,这里我们可以首先看数据库的初始化

var db *gorm.DB

func Init() error {
	var err error
	dsn := "root:root@tcp(127.0.0.1:3306)/community?charset=utf8mb4&parseTime=True&loc=Local"
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})

	return err
}

很简单的一个Init函数,用于初始化数据库

接下来就是对应的三个文件分别对应数据库中的三个表

image.png

image.png

很容易看懂的结构也是,我们就对此,分析一个post文件吧

type Post struct {
	Id         int64     `gorm:"column:id"`
	ParentId   int64     `gorm:"column:parent_id"`
	UserId     int64     `gorm:"column:user_id"`
	Content    string    `gorm:"column:content"`
	DiggCount  int64     `gorm:"column:digg_count"`
	CreateTime time.Time `gorm:"column:create_time"`
}

func (Post) TableName() string { return "post" }

type PostDao struct{}

var postDao *PostDao
var postOnce sync.Once

func NewPostDaoInstance() *PostDao {
	postOnce.Do(func() {
		postDao = &PostDao{}
	})
	return postDao
}

func (*PostDao) QueryPostById(id int64) (*Post, error) {
	var post Post
	err := db.Where("id=?", id).Find(&post).Error
	if err == gorm.ErrRecordNotFound {
		return nil, nil
	}
	if err != nil {
		util.Logger.Error("find post by id err:" + err.Error())
		return nil, err
	}

	return &post, nil
}

func (*PostDao) QueryPostByParentId(parentId int64) ([]*Post, error) {
	var posts []*Post
	err := db.Where("parent_id = ?", parentId).Find(&posts).Error
	if err != nil {
		util.Logger.Error("find posts by parent_id err:" + err.Error())
		return nil, err
	}

	return posts, nil
}

func (*PostDao) CreatePost(post *Post) error {
	if err := db.Create(post).Error; err != nil {
		util.Logger.Error("create post err:" + err.Error())
		return err
	}
	return nil
}

首先就是创建了一个Post结构体去对应着表中的列,这样也就可以更好的去操作数据库

然后就是通过单例模式创建对应的数据库操作实例,从而避免了资源的浪费。

然后就是接下来的三个方法,就是QueryPostById通过id查询Post记录

QueryPostByParentId通过parentId查询多条post记录

CreatePost就是创建一条新的post

自此,我们就大概了解了如何通过go框架去操作数据库了

这时候也就剩下了最后一个文件夹,handler

这也就是处理程序的文件夹,用于处理对路由访问的并且返回对应所需结果的

我们可以看到有两个文件,启动publish_post就是将请求的队友结果返回

而query_page_info则是将对应的发布文章的请求进行处理并返回对应结果。

这里我们能够发现handler中的代码是调用了service层的方法的,这里我们也就可以剖析整个程序的流程了

server.go中的路由-----> handler------>service----->repository

这也就是整个该项目的流程了

也就和java很像感觉。

最后就是对于service层的讲解

这里也就还是两个文件,对应handler中的两个操作

由service层调用数据库操作,从而获取到对应的数据,从而将其能够将数据返回。

自此,这个小项目的结构也就明了了,这也能够更加方便我们之后自己去开发项目,也要有着对应的结构,这样才能更好的去快速编写对应的功能。

3、项目总结

最后就是对整个项目的总结,这里我们了解了gin框架,并且完成了第一个go语言项目的编写,我们需要详细明白对应的项目结构,有着清晰的项目结构,才能更好的保障我们代码的可读性,还是gin框架,我感觉还是算是比较简单的,但是对于其操作数据库来说,我感觉稍微有点麻烦,毕竟对于每一个表都需要一个go文件与其对应才能使用,这样感觉有点啰嗦了。当然也不是说不好,只是个人这么感觉而已。 最后就是类比go语言和java,我感觉go语言中特别多的就是对于错误的处理,经常需要使用err去接受错误,并且去判断错误,以及打印,这点稍微有点麻烦,不过也有好处,就是能够快捷的指导自己代码哪里有错误什么的,方便去进行修改。