【问题标题】:Golang - Scan for all structs of type somethingGolang - 扫描所有类型的结构
【发布时间】:2014-05-09 05:13:21
【问题描述】:

我是围棋的初学者。多年来,我可能认为其他语言太传统了,但这就是我想在 Go 中做的事情。假设以下用例

  1. 我有接口I,这个接口有函数start()和stop()
  2. 有许多实现接口的结构。结构 A、结构 B、结构 C
  3. 当应用程序启动时,我想在结构 A、B 和 C 上调用 start()
  4. 同样,当应用程序终止时,我想在 A、B、C 结构上调用 stop()。
  5. 我不想在代码中的任何位置硬编码结构 A、B 和 C 来调用启动/停止函数。这样当我以后添加struct D(也实现了接口I)时,代码会自动运行,无需修改。
  6. 为了实现这一点,我需要能够说“Hey Go,给我所有实现接口 I 的类型”。
  7. 如果我取回 A、B 和 C 的一部分,我可以简单地循环并在正确的时间调用正确的方法。

在 Go 中可行吗?

【问题讨论】:

  • 您仍然需要每个结构的值才能调用该方法(该值可以是nil)。无法对类型 (StructA.start()) 调用方法。那么,你想让这个循环创建一个结构类型的零值,然后调用方法start()吗?
  • 我不是指调用结构本身,而是调用结构的一个实例。所以也许 Go 的要求是“给我你知道的所有已知的接口实例”,我们得到其中的一部分。不知道有没有办法。

标签: reflection go


【解决方案1】:

简短的回答是:不,这是不可行的

Go 是一种严格类型的语言。这允许链接器省略应用程序不使用的类型定义、方法和函数。

这意味着,除非某个类型(例如结构 A)在某处被引用和使用,否则它将被省略。

但在您的评论中,您提到您不想要类型,而是想要实现该接口的任何类型的当前存在的实例

这也是不可能的。

替代方案

我的建议是创建一个全局地图(或切片):

var instMap = map[string]StartStopper

并让每个结构使用 init 函数向该映射添加一个实例,该函数将在应用程序启动时自动调用:

type A struct {}

func init() {
    instMap["A"] = new(A)
}

然后当你想启动所有实例时,只需遍历地图并调用 Start()

编辑

如果不是每个类型一个实例,而是每种类型有多个实例,那么每当创建新实例时,您都必须添加到映射(或切片)中。并且您必须记住在不再使用该实例时将其从地图中删除,否则垃圾收集器将无法处理它。

【讨论】:

  • 不是我所希望的——我在考虑更多的声明风格。一个结构实现了一个接口,在程序的其他地方,我可以动态地做簿记。使用 Map 的方法,现在 init 函数和与之无关的 Map 之间存在非常紧密的耦合。
  • 只是好奇,我不知道有任何语言可以让您找到由代码任意创建的类型的所有实例。有什么例子?
  • @DavidBudworth 我相信 OP 正在寻求依赖注入方法。也就是说,他不一定对某个类型的特定内存实例感兴趣,而是想扫描类型并根据某些标准进行实例化。例如,考虑一个带有任务/动词等的命令行应用程序。
  • @DavidBudworth 在 C# 或 Java 等语言中通过反射实现微不足道。示例:stackoverflow.com/questions/26733/…
  • 这不起作用。仅在引用相关文件时才调用 init() 函数
猜你喜欢
  • 1970-01-01
  • 2013-10-22
  • 1970-01-01
  • 2020-02-15
  • 1970-01-01
  • 1970-01-01
  • 2017-10-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多