首先就是这次文章是怎么来的,是因为在训练营中看到了第四课,讲的是Go语言工程实践以及对应使用的gin框架,但是发现项目全套代码是有了,但是却没有分段的对应代码,应该是后边课程讲的但是没在此次训练营的课程表中吗,所以在此也是根据自己的理解对该项目进行一定的记录学习。并且,由于是直接对于一个项目进行分析的,就不过多对于理论部分进行讲解了。
1、Gin框架。
gin框架也是go中的一个最常见的框架了,能够让我们快速的启动一些http服务,非常的方便快捷。这里也就不多介绍了,本篇文章的侧重点是项目分析,这个也不是很难,可以直接看官方文档即可。gin-gonic.com/zh-cn/docs/…
2、项目结构
首先就是我们可以去分析一下项目的结果,这里我将给的项目中的一些测试以及知识点代码都去掉了,剩下了这些代码,并且其中service是用来测试项目功能的
接下来我们就是对这些代码进行理解。
首先就是启动项,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函数,用于初始化数据库
接下来就是对应的三个文件分别对应数据库中的三个表
很容易看懂的结构也是,我们就对此,分析一个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去接受错误,并且去判断错误,以及打印,这点稍微有点麻烦,不过也有好处,就是能够快捷的指导自己代码哪里有错误什么的,方便去进行修改。