Go 没有泛型,业务逻辑相似的 grpc 调用代码如何能更优雅一些? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
xmcy0011
V2EX    Go 编程语言

Go 没有泛型,业务逻辑相似的 grpc 调用代码如何能更优雅一些?

  •  
  •   xmcy0011 2020-10-22 19:58:17 +08:00 4979 次点击
    这是一个创建于 1846 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有个 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") } } 
    17 条回复    2020-11-10 14:24:26 +08:00
    BoarBoar
        1
    BoarBoar  
       2020-10-22 20:40:04 +08:00
    一般都是 interface{}代替泛型,不过会写很多用反射或者断言去判断 interface 持有类型的代码,用得少的话没必要搞
    lance6716
        2
    lance6716  
       2020-10-22 23:00:18 +08:00 via Android
    我当时用的运行时和反射。当时也考虑过 go generate template…
    fuis
        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")
    }
    }
    }

    ```
    hakono
        4
    hakono  
       2020-10-22 23:44:14 +08:00 via Android
    反射会影响程序性能
    beidounanxizi
        5
    beidounanxizi  
       2020-10-23 01:44:11 +08:00
    别整反射 去看看 go proverb
    泛型 去用回 JAVA 吧
    没泛型 更优雅
    deepreader
        6
    deepreader  
       2020-10-23 04:21:39 +08:00
    等 go 1.15 支持泛型吧 https://blog.golang.org/why-generics
    raaaaaar
        7
    raaaaaar  
       2020-10-23 07:08:59 +08:00 via Android
    在写了在写了,别催
    xuanbg
        8
    xuanbg  
       2020-10-23 07:37:06 +08:00
    用不着泛型,log 的内容可以参数拼接,发送的内容可以先序列化再作为参数传入进行发送。你需要的只是分拆几个静态方法而已。
    eudore
        9
    eudore  
       2020-10-23 08:56:53 +08:00
    不是有 pb 插件自动生成的调用代码? 你还自己手写个啥
    zunceng
        10
    zunceng  
       2020-10-23 09:04:20 +08:00
    我在自己的 infra 里面写了个代码生成的脚本
    mikulch
        11
    mikulch  
       2020-10-23 10:43:31 +08:00 via iPhone
    @beidounanxizi 已经在做了,这个语法。
    joesonw
        12
    joesonw  
       2020-10-23 11:44:46 +08:00
    自己写个 protoc-plugin 进去, 生成 go 代码?
    troywinter
        13
    troywinter  
       2020-10-23 13:55:37 +08:00
    传个闭包进来,用户使用时,在 func 里自己 cast 到想要的类型,稍微嗦一两行。
    xmcy0011
        14
    xmcy0011  
    OP
       2020-11-05 10:58:34 +08:00
    @fuis 感谢,vinterface{}是正解。同时感谢 @beidounanxizi go 之禅第一次听说,我这里补个链接,大家有空可以研究一下,类似于编码习惯和修养的东西。https://senseis.xmp.net/?GoProverbs
    xmcy0011
        15
    xmcy0011  
    OP
       2020-11-05 11:23:19 +08:00
    抱歉,链接上是个啥玩意。 @beidounanxizi 能贴个链接吗?
    beidounanxizi
        16
    beidounanxizi  
       2020-11-05 18:07:59 +08:00
    @xmcy0011 第一个结果就是 你干嘛贴第二个? https://go-proverbs.github.io/
    xmcy0011
        17
    xmcy0011  
    OP
       2020-11-10 14:24:26 +08:00
    @beidounanxizi 非常感谢,拜读。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     1363 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 23ms UTC 17:05 PVG 01:05 LAX 09:05 JFK 12:05
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86