问题描述
我希望在程序的任何阶段,对给定包中定义的结构的所有实例执行操作。为了做到这一点,我考虑过开发一个收集这些实例的函数。但是我还没有发现任何东西。
为了阐明我的目标(在回答“ @Muffin Top”和“ @Volker”之后),我目前正在手动对每个程序包中的指针存储进行此注册。这种方法存在两个问题,注册是一项普通的任务,并且容易出错。
为使情况更清楚,请考虑具有一个结构foo
的软件包Foo
。 Foo
有一个string
字段Name
。该软件包还定义了两个Foo
实例,分别声明为Foo1
和Foo2
package foo
type Foo struct {
Name string
}
var Foo1,Foo2 = Foo{Name: "Foo1"},Foo{Name: "Foo2"}
我要实现的GetInstancesOfPkg
如下例所示。要执行的操作仅是打印Name
字段。
这是一个有效的示例,但其模型版本为GetInstancesOfPkg
。
package main
import (
"log"
"reflect"
"github.com/thomaspeugeot/test-heapdump/foo"
)
func main() {
s := GetInstancesOfPkg("github.com/thomaspeugeot/test-heapdump/foo")
for _,instance := range s {
// cast instance on foo.Foo
if f,ok := instance.(*foo.Foo); !ok {
log.Panic("Unknown Struct " + reflect.TypeOf(instance).Name())
} else {
log.Printf("Instance of Foo has name %s ",f.Name)
}
}
}
// GetInstancesOfPkg return a slice of instances of Struct defined in the package pkgPath
// --- this is the mockup verion ---
func GetInstancesOfPkg(pkgPath string) (interfaceSlice []interface{}) {
var listOfFooInstances = []*foo.Foo{&foo.Foo1,&foo.Foo2}
interfaceSlice = make([]interface{},len(listOfFooInstances))
for i,d := range listOfFooInstances {
interfaceSlice[i] = d
}
return
}
对于该解决方案,我知道reflect
标准库或我所知道的任何其他库中都没有这样的功能。但是,我正在考虑:
-
一种算法,它解析整个程序存储器,识别每个变量,获取其类型并收集与程序包的结构类型匹配的变量。由于delve和heapdump确实解析了整个内存,并且delve可以猜测变量类型,所以我有直觉可以实现所需的功能。我一直在尝试研究delve的工作方式或heapcoredump的开发方式,但这是一项太多的知识,无法吞噬达到预期的目标。
-
另一种选择是添加一个预编译步骤,该步骤通过在每次变量初始化时添加注册来修改抽象语法树(AST)。
-
我什至不确定go能否实现这种水平的反射(或者它是否可以携带?)
-
性能不是问题,可以使用必需的wathever标志来编译程序,或者可以分析整个内存。
解决方法
有没有办法动态地收集给定结构类型的实例?
否。
您必须重新设计,例如通过记忆实例的函数分配实例。