V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
The Go Programming Language
http://golang.org/
Go Playground
Go Projects
Revel Web Framework
bakabie
V2EX  ›  Go 编程语言

OOP 好难啊.jpg

  •  
  •   bakabie ·
    9bie · 2019-09-28 23:51:50 +08:00 · 3671 次点击
    这是一个创建于 1887 天前的主题,其中的信息可能已经有所发展或是发生改变。

    有几个数据库模型( Novel,Archives ),都是要增删改查的。用的是 Echo 框架。 本来想打算每个模型都对应一个请求模型,再 bind 到不同的 API。 即:

    type NovelRequestGet struct{}
    type NovelRequestDelete struct{}
    ...
    type ArchiveRequestGet struct{}
    type NovelRequestDelete struct{}
    .....
    echo.bind(&NovelRequest)
    bind......
    

    然后数据库操作一波,返回。

    但是实际写的时候转念一想这不就是 CVM 嘛,除了传入变量类型不同其他代码完全一致。于是就用了 Interface。

    type GetInterface interface {
    	Get()*serializer.Response  //数据库查询操作
    	Response() *serializer.Response //返回数据
    }
    
    func Get(service _interface.GetInterface)echo.HandlerFunc {
    	return func(c echo.Context) (err error){
    		if err := c.Bind(&service); err == nil {
    			if err := service.Get(); err != nil {
    				return c.JSON(200, err)
    			} else {
    				res := service.Response()
    				return c.JSON(200, res)
    			}
    		} else {
    			return c.JSON(200, &serializer.Response{
    				Status: 40001,
    				Msg:    "参数错误",
    				Error:  fmt.Sprint(err),
    			})
    		}
    	}
    }
    

    最后绑定路由

    var ArchiveGet archive.GetService  
    route.GET("/archive/:id", api.Get(&ArchiveGet))
    

    这样本以为就可以实现泛型了,只要增删改查的业务就可以直接丢进来了。

    然而,理想很美好,显示很骨干。

    实际上运行

    {
        "status": 40001,
        "data": null,
        "msg": "参数错误",
        "error": "code=400, message=binding element must be a struct"
    }
    

    还必须要转成 struct。。。

    现在问题来了,请问各位老哥们:

    1. 我这样设计有错吗
    2. 如何解决目前这个问题

    目前感觉唯一的解法似乎就是自己整一个反射然后再 Bind,但是感觉在这样弄一个 Interface{}的意义似乎就没有了?

    请各位大佬解惑,小弟在此谢谢大家了

    7 条回复    2019-10-02 09:27:52 +08:00
    mcfog
        1
    mcfog  
       2019-09-29 07:58:34 +08:00 via Android   ❤️ 1
    云程序员来了!
    首先我没用过 echo (略

    golang 的 struct 不是 class,不要试图带入基于 class 的 oop 的范式

    一般而言,要复用用组合,要多态用 interface,要封装分 package 用 unexported type/field 完事儿

    //要泛型等 go2
    janxin
        2
    janxin  
       2019-09-29 09:06:32 +08:00   ❤️ 1
    你看,我就比较简单了,我就只会用

    type NovelRequest struct{}
    type ArchiveRequest struct{}
    tairan2006
        3
    tairan2006  
       2019-09-29 09:28:00 +08:00   ❤️ 1
    我也没用过 echo,不过我猜你应该这么设计:

    根据`/archive/:id`中 id 绑定的具体参数,利用工厂模式生成不同的 struct。然后这些 struct 都实现了 interface,转换一下就行了,后面代码是一样的。
    bakabie
        4
    bakabie  
    OP
       2019-09-29 11:23:57 +08:00
    @tairan2006 其实主要是工厂模式返回的 Struct 依旧是用 interface 返回出来的,而返回是 interface 的话,那个 bind 函数就用不了了
    bakabie
        5
    bakabie  
    OP
       2019-09-29 11:25:41 +08:00
    @janxin 其实 xxxRequests 是必要有的,只是我想能不能省略一下 Bind。。毕竟每次 Bind 完的操作都是执行一样的函数,我就在想能不能只写一个 Bind,,,
    bakabie
        6
    bakabie  
    OP
       2019-09-29 11:29:30 +08:00
    感谢诸位解惑。解决了。其实是我的锅。。把 Bind 中的&去掉就行了,我丢人了丢人了,快 TMD 溜。。。
    popbones
        7
    popbones  
       2019-10-02 09:27:52 +08:00
    grpc 了解下
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1059 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 22:20 · PVG 06:20 · LAX 14:20 · JFK 17:20
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.