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

2018-01-30 19:28:01 +08:00
 Morriaty

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 ...
}
1997 次点击
所在节点    Go 编程语言
16 条回复
hjc4869
2018-01-30 19:28:39 +08:00
map
Morriaty
2018-01-30 19:32:12 +08:00
@hjc4869 可能我理解有误,我要的是 map 里能存 struct 的类,而不是 struct 的实例
naiba
2018-01-30 19:32:13 +08:00
reflect
rrfeng
2018-01-30 19:33:24 +08:00
写一个 newstruct 方法,用 map string func 存起来。
rrfeng
2018-01-30 19:35:23 +08:00
感觉应该从需求上去重新考虑一下。

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/427201

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX