Go语言学习路线 - 5.基础篇:从一个web项目来谈Go语言的技能点

本文涉及的产品
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
简介: 经过了 入门篇 的学习,大家已经初步了解Go语言的语法,也能写常见的代码了。接下来,我们就从一个Web项目入手,看看一些常见的技能与知识吧。我们先简单地聊一下这个Web项目的背景:我们要做的是一个简单的web系统 ,有前端同学负责界面的开发,后端不会考虑高并发等复杂情况。

从一个Web项目开始

经过了 入门篇 的学习,大家已经初步了解Go语言的语法,也能写常见的代码了。接下来,我们就从一个Web项目入手,看看一些常见的技能与知识吧。

我们先简单地聊一下这个Web项目的背景:我们要做的是一个简单的web系统 ,有前端同学负责界面的开发,后端不会考虑高并发等复杂情况。

我们先从一个Web请求出发,看看会涉及到哪些模块。

前端的请求生命周期

用户在web界面上点击了一个按钮,就由前端发起了一个请求。那这个请求的生命周期是怎么样的呢?

通常情况下,后端的工作是解析前端的数据,处理对应的业务逻辑,返回操作结果

这里,离不开三层概念:

  • API层:解析来自前端的数据,转化成go的数据结构
  • Service层:包含业务逻辑,是这个请求具体要做的事情
  • Dao层:数据持久化,也就是更新到数据库等,保证不丢失

不同框架有不同的命名方式,但我个人建议只关注这三层即可。

当然,这三层逻辑并不绝对,会因为项目特点有所调整,但整体的分层思路是不会变化的。我认为,如果你能真正地理解web的分层,对项目的框架就能掌握得很棒了。

接下来,我们自顶向下逐层聊聊。

第一层:API层

通常来说,API层只做三件事:

  1. 根据路由规则,调用具体的处理函数 ,常见的RESTful就是由URL+Method的作为路由规则;
  2. 解析文本或二进制数据到Go结构体,常见的是用json反序列化;
  3. 调用下一层Service的函数

抛开第三点暂且不谈,前两者比较容易理解,大家可以使用标准库里的net/httpencoding/json来完成。具体的代码我就不写了,网上示例非常多。

那么,API层这么简单,有什么学问嘛?这里,我建议大家看看两个开源库:

看看上面的示例,对比一下原生的net/http库写出来的代码,是否感觉可读性大大提高?没错,API层关键点之一的就是可读性

不过Gin相对于Mux非常重量级,学习起来成本很大;而Mux虽然可读性提高,但在解析http body数据这块效果不佳,还是需要逐个手写结构体。

所以,在我看来,这两个都并不是最佳方案,我非常建议有条件的项目能够直接引入 RPC级别的解决方案,例如gRPC。这块我会拿具体项目、花好几讲来好好说说。

在开发的过程中,我对API层的开发会重点关注这几点:

  • 可读性:可以快速地根据命名了解功能,如RESTful
  • 高度复用:如引入mux 中的各种 middleware,比如 防止panic用户认证 、日志打印等
  • 尽量薄:不做或少做业务逻辑处理,复杂处理都丢到service层
  • 文档化:将接口的相关参数通过文档给到前端或第三方,尽量做到自动化或半自动化

我再强调一下API层的重要性:API层是程序最关键的入口和出口,能很好地追踪到数据的前后变化情况。 一个优秀的API层实现,不仅能让我们少写很多重复性代码,也能大幅度地降低我们排查问题的效率。

第二层:Service层

Service层可以理解为服务层,是整个项目中最复杂、也是代码比重往往是最多的。它是一个项目最核心的业务价值所在。

Service是最灵活、也是最考验设计能力的,虽说没有一套固定的模式,但还是会有一定的套路

我分享一下个人的三个见解:

  1. 单元测试覆盖率要尽量高,这是一个高频迭代与重构的模块,也是最容易出现问题的部分;
  2. 深入实践 面向对象与DDD ,最锻炼工程师抽象、解耦等能力的模块;
  3. 选择合适的 设计模式 可大幅度地提升研发效率;

再提一句,请跃跃欲试的各位冷静一下,Service层是和业务一起成长的,前期没必要过度设计。我们把重点放在单元测试的编写上即可,适当地选用一些库来提高效率,如开源的stretchr/testify,内部的reflect等。

第三层:Dao层

Dao层常被理解为数据持久化层,但我们可以将它进行一定的延伸:将RPC调用也当做Dao层(不妨认为将数据持久化到了另一个服务),来适配微服务架构的场景。

严格意义上,RPC调用和普通的Dao差异有不少,但为了收敛话题,我们暂且不细分。

今天,我们不关注分布式场景下的各种数据问题,也不考虑各种存储中间件的特点,而是聚焦于一个问题:如何将内存中的对象持久化到数据库中。在编程领域,这部分的工具被称为ORM

以Go语言对接MySQL为例,最常见的为gorm,它能很便捷地将一个Go语言中的结构体,映射到MySQL数据库某个表中的一行数据。

请自行对比一下,用go官方的sql库写增删改查,与用gorm写增删改查的工作量差异。

关于Dao层,我认为有部分的实践是比较通用的:

  1. 选用官方或社区高频使用的库,避免后期出现功能缺失或性能瓶颈的问题;
  2. 灵活性比易用性更重要,通过一层浅封装,往往能更适配项目,达到更棒的易用性;
  3. 关注数据库的原理、而不是ORM工具的实现方式,数据库的原理是长期的积累,对技术选型和排查故障很有帮助。

至于不同的数据库ORM有不同的最佳实践,一一列举的工作量太大,我会在工程化的过程中选择性地讲解。

串联三层

到这里,我们对这三层有了初步的了解,可以总结为两边薄(API、Dao),中间厚(Service)

这里的实践需要大家不断打磨,比如说:

  • API与Dao会随着个人编程能力的提升,不断地总结出更好的编程实践;
  • 做性能优化时,优先考虑Dao,其次考虑API,这两部分的提效是最明显的;
  • 排查问题时,先分析API的出入口,再分析Dao的出入口,实在解决不了再去看Service(此时已经是严重的业务逻辑问题了);

到最后,相信大家对这三层认知会进一步提升:

  • API:服务对外的门面,通过一个接口定义就能了解大致实现原理;
  • Service:复杂的业务逻辑,非该服务的核心成员无需关注,而核心成员须重点维护;
  • Dao:无论是调用ORM还是SDK,都视为一种工具集,是一个技术人员沉淀通用能力的重点。

CRUD程序员

很多程序员都戏称自己是一个只会CRUD的码农。让我们换个视角,看看CRUD背后有没有一些的技术点。

  • API层:遵循RESTful的原则,提高可读性(最好能在一行代码中看到,如mux
    • 将操作(CRUD)对应到HTTP的Method
    • 将资源对象对应到HTTP的URL
  • Service层:
    • 对于只是简单的修改,Service不用做复杂处理,透传到Dao层即可
    • 如果涉及到多个表的修改,进行事务处理(如mysql的transaction)
    • 在Dao层出现错误时,适当封装错误信息,提高可读性
  • Dao层:
    • 选择并熟练运用ORM,快速实现基本的CRUD
    • 对复杂的ORM进行一层浅封装,方便Service层的调用

经过一段时间的磨练,CRUD的工作能大大提效,我们就能抽出更多的时间去学习其余技能了。

结束语

Web项目是我们日常开发最常见的项目类型,也是很多面试考察点的基点。

我建议大家从分层着手,明确各层职责,关注API与Dao层的提效工作,做好Service层的质量保障,更好地掌控全局。而在具体的开源库的使用过程中,选对比会用更重要,集中在API与Dao层

目录
打赏
0
0
0
0
18
分享
相关文章
监控局域网其他电脑:Go 语言迪杰斯特拉算法的高效应用
在信息化时代,监控局域网成为网络管理与安全防护的关键需求。本文探讨了迪杰斯特拉(Dijkstra)算法在监控局域网中的应用,通过计算最短路径优化数据传输和故障检测。文中提供了使用Go语言实现的代码例程,展示了如何高效地进行网络监控,确保局域网的稳定运行和数据安全。迪杰斯特拉算法能减少传输延迟和带宽消耗,及时发现并处理网络故障,适用于复杂网络环境下的管理和维护。
揭秘 Go 语言中空结构体的强大用法
Go 语言中的空结构体 `struct{}` 不包含任何字段,不占用内存空间。它在实际编程中有多种典型用法:1) 结合 map 实现集合(set)类型;2) 与 channel 搭配用于信号通知;3) 申请超大容量的 Slice 和 Array 以节省内存;4) 作为接口实现时明确表示不关注值。此外,需要注意的是,空结构体作为字段时可能会因内存对齐原因占用额外空间。建议将空结构体放在外层结构体的第一个字段以优化内存使用。
|
3月前
|
Go 语言入门指南:切片
Golang中的切片(Slice)是基于数组的动态序列,支持变长操作。它由指针、长度和容量三部分组成,底层引用一个连续的数组片段。切片提供灵活的增减元素功能,语法形式为`[]T`,其中T为元素类型。相比固定长度的数组,切片更常用,允许动态调整大小,并且多个切片可以共享同一底层数组。通过内置的`make`函数可创建指定长度和容量的切片。需要注意的是,切片不能直接比较,只能与`nil`比较,且空切片的长度为0。
Go 语言入门指南:切片
eino — 基于go语言的大模型应用开发框架(二)
本文介绍了如何使用Eino框架实现一个基本的LLM(大语言模型)应用。Eino中的`ChatModel`接口提供了与不同大模型服务(如OpenAI、Ollama等)交互的统一方式,支持生成完整响应、流式响应和绑定工具等功能。`Generate`方法用于生成完整的模型响应,`Stream`方法以流式方式返回结果,`BindTools`方法为模型绑定工具。此外,还介绍了通过`Option`模式配置模型参数及模板功能,支持基于前端和用户自定义的角色及Prompt。目前主要聚焦于`ChatModel`的`Generate`方法,后续将继续深入学习。
472 7
企业监控软件中 Go 语言哈希表算法的应用研究与分析
在数字化时代,企业监控软件对企业的稳定运营至关重要。哈希表(散列表)作为高效的数据结构,广泛应用于企业监控中,如设备状态管理、数据分类和缓存机制。Go 语言中的 map 实现了哈希表,能快速处理海量监控数据,确保实时准确反映设备状态,提升系统性能,助力企业实现智能化管理。
48 3
eino — 基于go语言的大模型应用开发框架(一)
Eino 是一个受开源社区优秀LLM应用开发框架(如LangChain和LlamaIndex)启发的Go语言框架,强调简洁性、可扩展性和可靠性。它提供了易于复用的组件、强大的编排框架、简洁明了的API、最佳实践集合及实用的DevOps工具,支持快速构建和部署LLM应用。Eino不仅兼容多种模型库(如OpenAI、Ollama、Ark),还提供详细的官方文档和活跃的社区支持,便于开发者上手使用。
555 8
Go 语言中的 Sync.Map 详解:并发安全的 Map 实现
`sync.Map` 是 Go 语言中用于并发安全操作的 Map 实现,适用于读多写少的场景。它通过两个底层 Map(`read` 和 `dirty`)实现读写分离,提供高效的读性能。主要方法包括 `Store`、`Load`、`Delete` 等。在大量写入时性能可能下降,需谨慎选择使用场景。
阿里双十一背后的Go语言实践:百万QPS网关的设计与实现
解析阿里核心网关如何利用Go协程池、RingBuffer、零拷贝技术支撑亿级流量。 重点分享: ① 如何用gRPC拦截器实现熔断限流; ② Sync.Map在高并发读写中的取舍。
106 0
Go语言实战:错误处理和panic_recover之自定义错误类型
本文深入探讨了Go语言中的错误处理和panic/recover机制,涵盖错误处理的基本概念、自定义错误类型的定义、panic和recover的工作原理及应用场景。通过具体代码示例介绍了如何定义自定义错误类型、检查和处理错误值,并使用panic和recover处理运行时错误。文章还讨论了错误处理在实际开发中的应用,如网络编程、文件操作和并发编程,并推荐了一些学习资源。最后展望了未来Go语言在错误处理方面的优化方向。
基于 Go 语言的公司内网管理软件哈希表算法深度解析与研究
在数字化办公中,公司内网管理软件通过哈希表算法保障信息安全与高效管理。哈希表基于键值对存储和查找,如用户登录验证、设备信息管理和文件权限控制等场景,Go语言实现的哈希表能快速验证用户信息,提升管理效率,确保网络稳定运行。
43 0

热门文章

最新文章

AI助理

你好,我是AI助理

可以解答问题、推荐解决方案等