Golang – 扫描所有类型为something的结构体

huangapple go评论85阅读模式
英文:

Golang - Scan for all structs of type something

问题

我是Go的初学者。可能因为在其他语言中度过了多年,我可能会想得太传统,但这是我想在Go中做的事情。假设以下使用情况:

  1. 我有一个接口I。这个接口有两个函数,start()和stop()。
  2. 有许多结构体实现了这个接口。结构体A、结构体B、结构体C。
  3. 当应用程序启动时,我想在结构体A、B和C上调用start()。
  4. 同样地,当应用程序终止时,我想在结构体A、B和C上调用stop()。
  5. 我不想在代码的任何地方硬编码结构体A、B和C来调用start/stop函数。这样,当我稍后添加结构体D(也实现接口I)时,代码将自动工作而无需修改。
  6. 为了实现这一点,我需要能够说:“嘿,Go,给我所有实现接口I的类型。”
  7. 如果我得到一个包含A、B和C的切片,我可以简单地循环遍历并在适当的时间调用正确的方法。

在Go中可行吗?

英文:

I am a beginner in Go. I maybe thinking too traditional coming from years in other languages, but here is what I want to do in Go. Assume the following use case

  1. I have interface I. This interface has functions, start() and stop()
  2. There are many structs implementing the interface. struct A, struct B, struct C
  3. When the application starts, I want to call start() on structs A, B and C
  4. Similarly, when the application terminates, I want to call stop() on the A, B, C structs.
  5. I do not want to hard code struct A, B and C anywhere in the code to call the start/stop functions. This is so that when I add struct D later (also implements interface I), the code will automatically work without modification.
  6. In order to achieve this, I need to be able to say "Hey Go, give me all the types that implement interface I".
  7. If I get back a slice of A, B and C, I can simply loop through and call the right methods at the right time.

Doable in Go?

答案1

得分: 8

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

Go是一种严格类型的语言。这使得链接器可以省略应用程序中未使用的类型定义、方法和函数。

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

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

这也是不可能的。

替代方案

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

var instMap = map[string]StartStopper

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

type A struct {}

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

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

编辑

如果不是每种类型只有一个实例,而是每种类型有多个实例,那么你将需要在创建新实例时将其添加到映射(或切片)中。并且在不再使用实例时记得从映射中删除该实例,否则它将不会被垃圾回收器处理。

英文:

The short answer is: No, that is not doable

Go is a strictly typed language. This allows the linker to leave out type definitions, methods and functions not used by the application.

That means, unless a type (such as struct A) are referenced and used somewhere, it will be omitted.

But in your comment, you mentioned you don't want the types but rather the currently existing instances of any type that implements the interface.

This is not possible either.

Alternative

My suggestion is to create a global map (or slice):

var instMap = map[string]StartStopper

And have each struct add an instance to that map with an init function that will automatically be called at the start of the application:

type A struct {}

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

Then when you want to start all the instances, just iterate over the map and call Start()

Edit

And if it is not a one-instance-per-type situation but rather multiple instances for each type, then you will have to add to the map (or slice) whenever a new instance is created. And you would have to remember deleting the instance from the map when it is not to be used anymore, or else it won't be handled by the Garbage Collector.

huangapple
  • 本文由 发表于 2014年5月9日 13:13:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/23557048.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定