经过了 入门篇 的学习,大家已经初步了解Go语言的语法,也能写常见的代码了。接下来,我们就从一个Web项目入手,看看一些常见的技能与知识吧。
我们先简单地聊一下这个Web项目的背景:我们要做的是一个简单的web系统 ,有前端同学负责界面的开发,后端不会考虑高并发等复杂情况。
我们先从一个Web请求出发,看看会涉及到哪些模块。
用户在web界面上点击了一个按钮,就由前端发起了一个请求。那这个请求的生命周期是怎么样的呢?
通常情况下,后端的工作是解析前端的数据,处理对应的业务逻辑,返回操作结果。
这里,离不开三层概念:
不同框架有不同的命名方式,但我个人建议只关注这三层即可。
当然,这三层逻辑并不绝对,会因为项目特点有所调整,但整体的分层思路是不会变化的。我认为,如果你能真正地理解web的分层,对项目的框架就能掌握得很棒了。
接下来,我们自顶向下逐层聊聊。
通常来说,API层只做三件事:
URL
+Method
的作为路由规则;json
反序列化;抛开第三点暂且不谈,前两者比较容易理解,大家可以使用标准库里的net/http
和encoding/json
来完成。具体的代码我就不写了,网上示例非常多。
那么,API层这么简单,有什么学问嘛?这里,我建议大家看看两个开源库:
看看上面的示例,对比一下原生的net/http
库写出来的代码,是否感觉可读性大大提高?没错,API层关键点之一的就是可读性。
不过Gin相对于Mux非常重量级,学习起来成本很大;而Mux虽然可读性提高,但在解析http body
数据这块效果不佳,还是需要逐个手写结构体。
所以,在我看来,这两个都并不是最佳方案,我非常建议有条件的项目能够直接引入 RPC级别的解决方案,例如gRPC。这块我会拿具体项目、花好几讲来好好说说。
在开发的过程中,我对API层的开发会重点关注这几点:
mux
中的各种 middleware,比如 防止panic 、用户认证 、日志打印等我再强调一下API层的重要性:API层是程序最关键的入口和出口,能很好地追踪到数据的前后变化情况。 一个优秀的API层实现,不仅能让我们少写很多重复性代码,也能大幅度地降低我们排查问题的效率。
Service层可以理解为服务层,是整个项目中最复杂、也是代码比重往往是最多的。它是一个项目最核心的业务价值所在。
Service是最灵活、也是最考验设计能力的,虽说没有一套固定的模式,但还是会有一定的套路。
我分享一下个人的三个见解:
再提一句,请跃跃欲试的各位冷静一下,Service层是和业务一起成长的,前期没必要过度设计。我们把重点放在单元测试的编写上即可,适当地选用一些库来提高效率,如开源的stretchr/testify
,内部的reflect
等。
Dao层常被理解为数据持久化层,但我们可以将它进行一定的延伸:将RPC调用也当做Dao层(不妨认为将数据持久化到了另一个服务),来适配微服务架构的场景。
严格意义上,RPC调用和普通的Dao差异有不少,但为了收敛话题,我们暂且不细分。
今天,我们不关注分布式场景下的各种数据问题,也不考虑各种存储中间件的特点,而是聚焦于一个问题:如何将内存中的对象持久化到数据库中。在编程领域,这部分的工具被称为ORM。
以Go语言对接MySQL为例,最常见的为gorm,它能很便捷地将一个Go语言中的结构体,映射到MySQL数据库某个表中的一行数据。
请自行对比一下,用go官方的sql库写增删改查,与用gorm写增删改查的工作量差异。
关于Dao层,我认为有部分的实践是比较通用的:
至于不同的数据库ORM有不同的最佳实践,一一列举的工作量太大,我会在工程化的过程中选择性地讲解。
到这里,我们对这三层有了初步的了解,可以总结为两边薄(API、Dao),中间厚(Service) 。
这里的实践需要大家不断打磨,比如说:
到最后,相信大家对这三层认知会进一步提升:
很多程序员都戏称自己是一个只会CRUD的码农。让我们换个视角,看看CRUD背后有没有一些的技术点。
mux
)经过一段时间的磨练,CRUD的工作能大大提效,我们就能抽出更多的时间去学习其余技能了。
Web项目是我们日常开发最常见的项目类型,也是很多面试考察点的基点。
我建议大家从分层着手,明确各层职责,关注API与Dao层的提效工作,做好Service层的质量保障,更好地掌控全局。而在具体的开源库的使用过程中,选对比会用更重要,集中在API与Dao层。
Github: https://github.com/Junedayday/code_reading Blog: http://junes.tech/ Bilibili: https://space.bilibili.com/293775192 公众号: golangcoding