Junedayday Blog

六月天天的个人博客

0%

【每周小结】2023-Week8

这段时间,我在尝试着远离抖音、B站、头条等消息媒介。

这些平台承载了过多大数据推荐算法,反复向人们推送着高度重复性的内容,脱离了获取信息的初衷 - 扩大自己的认知面。如果你关注的内容包括了失业等负面内容,还容易加强你的焦虑感。

Go技巧 - 结构体的赋值小技巧

在日常的CRUD开发过程中,我们往往会用到一些结构体:它们只是一些简单的数据的组合,很难用对象来封装。比如说,有一个订单表,里面包括20+个field。当我们创建时,就需要对这些field赋值。

1
2
3
type Order struct {
// 包括近20个字段
}

下面,我们来看三种常见的方法,并分析各自的利弊:

方案1-全量透传结构体

1
2
3
4
5
6
7
8
9
// 数据从http body中解析出来
var b []byte

// 解析到order
var order = new(Order)
json.Unmarshal(b, &order)

// 创建到数据库
db.Insert(order)

这种思路确实非常方便,但仅限于轻量级项目。

如果业务逻辑稍微复杂点,就会出现无法支持的情况。问题的根本在于:在程序的不同层面,结构体各有各的使用场景,像传输效率、安全、性能等

最经典的莫过于时间类型的参数:在数据库保存为timestamp格式,而在接口层往往是YYYY-MM-DD hh:mm:ssint64类型,无法用透传实现。

方案2-用一个通用库解决问题

既然我们要从一个结构体转成另一个结构体,就自然产生了一个想法 - 写个通用库。

常见的实现思路有2种:序列化工具或发射。这里以序列化工具为例:

1
2
3
4
5
6
7
8
9
// 源结构体,来自http
type OrderDTO struct{}
// 目标结构体,保存到MySQL
type OrderDao struct{}

var order *orderDTO
b, err := json.Marshal(order)
var target = new(OrderDao)
err = json.Unmarshal(b, target)

这种思路在编写代码时确实方便,但是,长期来看有两大隐患:

  1. 中间操作的性能可能成为性能瓶颈
  2. 两个结构体不一定能保证一致,如数据库里叫name,但接口则叫order_name

尤其是第二点,使得通用库变得不再通用,就会出现一些tricky的实现,比如:

1
2
3
type Order struct {
Name string `json:"order_name"`
}

这种方式很容易在未来成为一个埋雷点。随着通用库的封装,埋雷越来越多,往往就变得不可维护了。

方案3-傻瓜式赋值

1
2
3
4
5
6
7
8
9
func transfer(from *orderDTO) (to *OrderDao){
return OrderDao {
Id: from.Id,
Name: from.OrderName,
CreateTime: from.CreateTime.Format("2006-01-02 15:04:05"),
Cost: from.EndTime.Sub(from.StartTime).Seconds(),
// ...
}
}

这样的代码写起来很累,但对阅读者来说是非常方便的(往往封装成一个函数,放在文件末尾即可)。在开发与排查问题的过程中,它有三个优点无可比拟:

  1. 填充逻辑清晰:数据源来自哪个字段,又被填充到了哪个字段,一目了然
  2. 灵活自定义加工:如代码中时间CreateTime的格式化,以及耗时Cost的逻辑计算
  3. 兼容性与安全性高:两个结构体的变更,要么不影响这个转换逻辑(兼容性高,如新增字段),要么就会编译报错(安全性高,如修改相关字段的名称或类型)

小结

在我开发Go语言的近六年时间里,看到相关的代码风格远不止这3种。通过反反复复倒腾,我认为代码可维护性最为重要,所以更倾向于 傻瓜式赋值 这个方法,哪怕牺牲一部分效率也是值得的(在IDE的帮助下,其实效率几乎没有影响)。

你的想法又是怎么样呢?欢迎与我交流沟通。

编程思考 - 重视技术评审的过程性价值

我们模拟个场景:你写了一个自认为 当下最优解的技术方案,信心满满地拿出来评审,结果遭到各方的挑战,无法回答清楚很多问题,心里忿忿不平;评审后仍按你的方案执行,结果出来也很不错,你就觉得当时提问的那些评委都不如你。

相信很多人都有这样的经历,我也相当一段时间处于这种状态。不过,现在的我更愿意静下心,去关注过程里的一些内容:

  • 评委提出的“无意义”问题,是否有一部分来源于我叙述的不清楚?尤其是背景
  • 评委们关心的角度是否与我的视角有差异?比如我更关心代码实现,而评委关注的是业务、稳定性、安全等
  • 你获得的成果,是否仍有改进空间?适当地收集一些评委意见,弥补个人视角的盲区

技术评审的主要价值是 优化方案。作为评审方,大部分的评委在多方面的能力都是高于本人的。如果你抱着“评委就是跟我过不去、就是乱挑刺”的想法去面对他们,那么对你来说就是浪费时间。

如果真有这么一个瞎挑刺的评委、他又是你工作中绕不过的领导,那该怎么办呢?退而求其次,技术评审还提供了一个交流的机会,你可以尝试着摸清他的一些思路,想想如何与其相处,为自己营造更轻松的工作环境

工作生活 - 主动创造美好瞬间

这个小标题起得有点煽情。

我想表达的是:在年轻时,我们可以肆意地享受人生的美好。但随着时间推移,我们往往会被家庭琐事、工作压力、身体健康等问题困扰,这就需要我们从被动的享受、慢慢地转变为主动创造,这样就能大幅提高生活的幸福感。

而且,我们创造的美好瞬间能让家人与朋友同样感受到快乐,提高整个圈子的幸福感;而整体氛围的提升,往往能形成正反馈,收益人也包括了你。

Github: https://github.com/Junedayday/code_reading

Blog: http://junes.tech/

Bilibili: https://space.bilibili.com/293775192

公众号: golangcoding

二维码