以前接触过的一个 Java 项目,实现了一种在我看来很新的做法:

  1. 代码生成的协议类,里面自带了一个未实现的 process 方法
public class Echo extend Msg {
	String msg;
  	public void decode(){}
  	public void encode(){}
  	public void process() throws Exception {
  		throw new UnsupportedOperationException();
  	}
}
  1. 代码生成的协议处理类,格式是这样的
@MsgProcess
public static boolean process(Echo echo) {
	return true;
}
  1. 框架启动的时候,会反射获取到注解@MsgProcess的 Metchod 和他的参数,然后用 javaassist 的字节码操作,将协议类Echoprocess方法给替换掉!这样框架层调用协议的msg.process()就可以直接执行业务逻辑!

Java 写了 10 年,一说起框架,自然想到的就是各种设计模式抽象继承与反射之类,当写 Go 的时候,也受到影响,我现在想用 Go 实现类似的操作,实践的效果如下

  1. 代码生成了 Echo 协议类
package proto
type Echo struct {
	BaseMsg
	Msg string
}
func (msg *Echo) Decode(src *bytes.Buffer) error {}
func (msg *Echo) Encode(dst *bytes.Buffer) error {}
func (msg *Echo) Process() {
	panic("implement me")
}
  1. 代码生成了业务逻辑类
package logic
import proto
func ProcessEcho(msg *proto.Echo) {}
  1. 使用 ast/parser 将Echoprocess的方法体替换为ProcessEcho
func (msg *Echo) Process() {
	logic.ProcessEcho(msg)
}

但重新生成的 Echo 类,有一些问题,首先生成出来的文件,我将其保存为echo_override.go放在另一个 package ,相关的 import 都可能有问题,然后Processimport 了 logic ,而 logic 自然要 import echo ,非常经典的 import cycle 。

这是第一步遇到的问题,我打算先用 interface 解决看看,为什么不用 func 替换,我觉得好丑啊!各位 Go 大神有没有什么建议?我这种思路,符合 Go 的设计哲学吗?

举报· 3351 次点击
登录 注册 站外分享
31 条回复  
NessajCN 小成 2024-12-6 12:50:37
在我看来只需要定义 func Process(msg *Echo)就够了,再来个 ProcessEcho 意义何在
yolee599 初学 2024-12-6 12:54:48
我是不喜欢反射,反射会让代码变得不可预测
assiadamo 楼主 小成 2024-12-6 12:59:00
@NessajCN 因为不要去 proto 包下生成的协议类中写业务逻辑,想把两边的编码隔离开
cookii 小成 2024-12-6 13:04:48
@yolee599 同不喜欢反射,滥用反射的场景太多了。
zjsxwc 小成 2024-12-6 13:09:56
把 echo.go 改名成 echo.go.proto ,把 echo_override.go 改名成 echo.go 呗
NessajCN 小成 2024-12-6 13:12:06
@assiadamo 那就直接在 logic 里定义 Process 啊,proto 那里那个不用了呗
assiadamo 楼主 小成 2024-12-6 13:15:21
@zjsxwc 有点天才,可以一试
assiadamo 楼主 小成 2024-12-6 13:16:42
@NessajCN 框架想做到不接触业务层,直接调用协议的`msg.Process()`就能执行业务逻辑,否则还要手动将业务层的各种协议处理函数注册一下
NessajCN 小成 2024-12-6 13:21:16
@assiadamo 你一边说不想在框架里写业务,一边又说直接调用框架里的方法执行业务逻辑,你到底想说啥?
1234下一页
返回顶部