简介
在做个人项目go-aspect 过程中,经历过多种编织方式,这种方式的递进,主要的思路是建立在尽可能减少对原业务代码的影响,接下来会按顺序逐个介绍下不同的编织方式。
直接在原方法内编织
这种方式是最直接也是最容易想到的方式,直接在待织入的代码在编译时织入到对应的方法中,比较直接,比较容易实现,但对原业务代码的影响也是最大的,主要集中在一下几点
- 不利于around环绕模式切入
- 对原业务代码行数的影响较大,主要是日志中显示的代码行数和源码不同
- 切入代码和原业务代码柔和在一起,不利于后续排查问题
在源代码尾部进行追加
这种方式需要使用新追加的方法来替代原方法,修改原方法的方法名,在尾部新方法中使用target方式进行调用原方法,这种方式的好处是将切入的代码和原业务代码进行分离,减少了对原方法的影响,但也有几点问题
- 实现较第一种方式更为复杂
- 切入代码引入的import,同样会影响代码行数,但相较于第一种方式要小很多
- 修改了方法名,日志中显示的调用方法名与源码不同
- 对defer方式无效
在新文件中进行追加
这种方式主要是对上一种方式import问题的优化,新建一个新文件,则其import可以独立引入,不会对源文件产生影响,但日志中和debug时方法不对应的问题仍然存在,这也是目前go-aspect 项目使用的方式
利用嵌入式结构体
修改原方法的接受者,如无接受者,则添加一个接收者,类似下面方法
- 原方法:
func (t TS) m() {
}
- 新方法:
type TSS struct {
TS
}
func (t TSS) m() {
}
该中方案是在上一方案上的递进,能够比较好的解决上一方案遗留的因方法名被修改导致的一系列问题。
总结
以上是本人在做go-aspect 项目时对编织手段的一种递进,最后一种方式是目前已经支持的,后续如果有更好的方案会持续优化。