有个 gate 网关,包装一层 grpc 调用 logic 上的接口,协议使用的 protobuf 。大致业务流程都差不多: 1.反序列化成对象 2.调用 grpc 接口 3.根据结果,发送到客户端。
具体代码如下:
// 创建群
func (tcp *TcpConn) onHandleCreateGroup(header *cim.ImHeader, buff []byte) {
req := &cim.CIMGroupCreateReq{}
err := proto.Unmarshal(buff, req)
if err != nil {
logger.Sugar.Warnf("onHandleCreateGroup error")
return
}
logger.Sugar.Info("onHandleCreateGroup")
conn := GetMessageConn()
ctx, cancelFun := context.WithTimeout(context.Background(), time.Second*3)
defer cancelFun()
rsp, err := conn.CreateGroup(ctx, req)
if err != nil {
logger.Sugar.Warnf("CreateGroup(gRPC) err:", err.Error())
} else {
_, err = tcp.Send(header.SeqNum, uint16(GROUP_CREATE_DEFAULT_REQ), rsp)
logger.Sugar.Infof("onHandleCreateGroup CreateGroup(gRPC) res")
}
}
// 解散群
func (tcp *TcpConn) onHandleDisbandingGroup(header *cim.ImHeader, buff []byte) {
req := &cim.CIMGroupDisbandingReq{}
err := proto.Unmarshal(buff, req)
if err != nil {
logger.Sugar.Warnf("onHandleDisbandingGroup error")
return
}
logger.Sugar.Info("onHandleDisbandingGroup")
conn := GetMessageConn()
ctx, cancelFun := context.WithTimeout(context.Background(), time.Second*3)
defer cancelFun()
rsp, err := conn.DisbandingGroup(ctx, req)
if err != nil {
logger.Sugar.Warnf("DisbandingGroup(gRPC) err:")
} else {
_, err = tcp.Send(header.SeqNum, uint16(GROUP_DISBINGDING_RSP), rsp)
logger.Sugar.Infof("onHandleDisbandingGroup res")
}
}
1
BoarBoar 2020-10-22 20:40:04 +08:00
一般都是 interface{}代替泛型,不过会写很多用反射或者断言去判断 interface 持有类型的代码,用得少的话没必要搞
|
2
lance6716 2020-10-22 23:00:18 +08:00 via Android
我当时用的运行时和反射。当时也考虑过 go generate template…
|
3
fuis 2020-10-22 23:39:40 +08:00
@xmcy0011 随手写了一段,大概看个意思。基本思路就是把重复的地方抠出来做成 func,然后用另一个 helper func 去调用它们。参数尽量看准原来就使用 interface{} 的地方,这样不用写很多 type assert
```go func (tcp *TcpConn) onHandleCreateGroup(header *cim.ImHeader, buff []byte) { req := &cim.CIMGroupCreateReq{} call(header, buff, req, func() { return conn.CreateGroup(ctx, req) }, func(rsp Response) { _, err = tcp.Send(...) }) } func (tcp *TcpConn) onHandleDisbandingGroup(header *cim.ImHeader, buff []byte) { req := &cim.CIMGroupDisbandingReq{} call(header, buff, req, func () { return conn.DisbandingGroup(ctx, req) }, func(rsp Response) { _, err = tcp.Send(...) }) } func (t *TcpConn) call( header *cim.ImHeader, buff []byte, req interface{}, method string, rpcFn func(context.Context, interface{}) (Response, error), callback func(Response) error) func() { return func() { err := proto.Unmarshal(buff, req) if err != nil { logger.Sugar.Warnf("%s error", method) return } logger.Sugar.Info(method) conn := GetMessageConn() ctx, cancelFun := context.WithTimeout(context.Background(), time.Second*3) defer cancelFun() rsp, err := rpcFn(ctx, req) if err != nil { logger.Sugar.Warnf("DisbandingGroup(gRPC) err:") } else { _, err := callback(rsp) logger.Sugar.Infof("onHandleDisbandingGroup res") } } } ``` |
4
hakono 2020-10-22 23:44:14 +08:00 via Android
反射会影响程序性能
|
5
beidounanxizi 2020-10-23 01:44:11 +08:00
别整反射 去看看 go proverb
泛型 去用回 JAVA 吧 没泛型 更优雅 |
6
deepreader 2020-10-23 04:21:39 +08:00
等 go 1.15 支持泛型吧 https://blog.golang.org/why-generics
|
7
raaaaaar 2020-10-23 07:08:59 +08:00 via Android
在写了在写了,别催
|
8
xuanbg 2020-10-23 07:37:06 +08:00
用不着泛型,log 的内容可以参数拼接,发送的内容可以先序列化再作为参数传入进行发送。你需要的只是分拆几个静态方法而已。
|
9
eudore 2020-10-23 08:56:53 +08:00
不是有 pb 插件自动生成的调用代码? 你还自己手写个啥
|
10
zunceng 2020-10-23 09:04:20 +08:00
我在自己的 infra 里面写了个代码生成的脚本
|
11
mikulch 2020-10-23 10:43:31 +08:00 via iPhone
@beidounanxizi 已经在做了,这个语法。
|
12
joesonw 2020-10-23 11:44:46 +08:00
自己写个 protoc-plugin 进去, 生成 go 代码?
|
13
troywinter 2020-10-23 13:55:37 +08:00
传个闭包进来,用户使用时,在 func 里自己 cast 到想要的类型,稍微啰嗦一两行。
|
14
xmcy0011 OP @fuis 感谢,vinterface{}是正解。同时感谢 @beidounanxizi go 之禅第一次听说,我这里补个链接,大家有空可以研究一下,类似于编码习惯和修养的东西。https://senseis.xmp.net/?GoProverbs
|
15
xmcy0011 OP 抱歉,链接上是个啥玩意。 @beidounanxizi 能贴个链接吗?
|
16
beidounanxizi 2020-11-05 18:07:59 +08:00
@xmcy0011 第一个结果就是 你干嘛贴第二个? https://go-proverbs.github.io/
|
17
xmcy0011 OP @beidounanxizi 非常感谢,拜读。
|