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

GO 中如何做到“读不同的配置,加载不同的类”

  •  
  •   Morriaty · 2018-01-30 19:28:01 +08:00 · 2116 次点击
    这是一个创建于 2489 天前的主题,其中的信息可能已经有所发展或是发生改变。

    python 的逻辑大致如下,但在 go 中不知道怎么做

    class A(object):
        def run(self):
            pass
    
    class B(object):
        def run(self):
            pass
    
    
    all_classes = {"a": A, "b": B}
    
    
    for class_type, args in read_config("config_file"):
        instance = all_classes[class_type](**args)
        # 或者
        instance = getattr(sys.modules[__name__], class_type.upper())
        instance.run()
    
        
    

    现在能想到的就是写一堆的 if else,然后返回一个 interface{},有更合理的方式吗?

    func LoadClass(class_type string, args map[string]string) interface{} {
        if class_type == "a" {
             ...
        } else if ...
    }
    
    16 条回复    2018-02-23 13:21:05 +08:00
    hjc4869
        1
    hjc4869  
       2018-01-30 19:28:39 +08:00 via iPhone
    map
    Morriaty
        2
    Morriaty  
    OP
       2018-01-30 19:32:12 +08:00
    @hjc4869 可能我理解有误,我要的是 map 里能存 struct 的类,而不是 struct 的实例
    naiba
        3
    naiba  
       2018-01-30 19:32:13 +08:00 via Android
    reflect
    rrfeng
        4
    rrfeng  
       2018-01-30 19:33:24 +08:00 via Android
    写一个 newstruct 方法,用 map string func 存起来。
    rrfeng
        5
    rrfeng  
       2018-01-30 19:35:23 +08:00
    感觉应该从需求上去重新考虑一下。

    如果 A 和 B 完全没任何关系,为什么要这样写?如果两者很类似,是不是有更好的数据结构?
    douglarek
        6
    douglarek  
       2018-01-30 20:21:32 +08:00 via iPhone
    定义一个接口 Runner 里面有一个方法 run,让不同的 struct 去实现 Runner 然后 loadclass 返回 Runner
    Archangel_SDY
        7
    Archangel_SDY  
       2018-01-30 23:21:44 +08:00
    map 里存 factory 函数.
    ZSeptember
        8
    ZSeptember  
       2018-01-30 23:41:21 +08:00   ❤️ 1
    Go 不能通过一个字符串反射出一个对象,所以先要将一个 struct 的构造方式注册。
    我们用的是 Model 接口有一个 New 方法,直接返回 new(Model),注册 model 到 factory,然后 factory 通过字符串返回 model 实例。
    Morriaty
        9
    Morriaty  
    OP
       2018-01-31 10:11:39 +08:00
    @rrfeng
    @douglarek
    目前就是按 type Runner interface{}这种方式做的,但不知道怎么返回一个 default 的空 interface,只能极其愚蠢的又实现了一个 type RunDefault struct {}
    douglarek
        10
    douglarek  
       2018-01-31 10:14:49 +08:00 via iPhone
    @Morriaty 那不可能啊 你定义的不是空接口肯定没法返回默认非空
    Morriaty
        11
    Morriaty  
    OP
       2018-01-31 10:32:09 +08:00
    @ZSeptember 注册 model 到 factory,这点能说详细点,或者给个示例代码吗?
    iRiven
        12
    iRiven  
       2018-01-31 10:43:17 +08:00 via Android
    你姿势不对。
    ZSeptember
        13
    ZSeptember  
       2018-01-31 10:56:07 +08:00
    @Morriaty new 一个空的 model。。这一步是没法省的。
    fortunezhang
        14
    fortunezhang  
       2018-01-31 10:58:41 +08:00
    简单点就是用 map
    复杂点就上设计模式。
    nekoyaki
        15
    nekoyaki  
       2018-02-23 13:14:38 +08:00   ❤️ 1
    你的思路不对,go 里不是这么考虑问题的,我提几个提示。
    1、golang 不是面向对象的语言,不要套用面向对象语言的设计模式。
    2、golang 如果想要实现类似根据不同的类实现多个逻辑的需求,你需要把它转换成结构体来考虑。
    3、func 在 golang 里是一等结构,因此结构体上可以有一些成员,这些成员的类型,是特定类型的 func。
    4、读取配置文件后,如果是 A 情况,则把该成员赋值为方法 A,如果是 B 情况,则把该成员赋值为方法 B。
    nekoyaki
        16
    nekoyaki  
       2018-02-23 13:21:05 +08:00
    接上条,手滑发出去了……
    5、这样实例 A 的 run 方法和实例 B 的 run 方法就可以实现不同的逻辑。
    伪代码举例如下:
    ```
    type Person Struct {
    name string
    tell func()(xxx)
    }



    zhangxiaojie = Person{ "baohua", func()(xxx) { fmt.println("Mr. dong lianren ? ") } }
    jiangxiansheng = Person { "takumin", func()(xxx) { fmt.println("Hou wa! ") }}


    zhangxiaojie.tell()
    jiangxiansheng.tell()
    ```
    这样两个人都是 person 实例,但 tell 方法的逻辑是不同的,不需要在方法逻辑里面来暴力 if else。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2886 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 09:04 · PVG 17:04 · LAX 01:04 · JFK 04:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.