I would like, at any stage in a program, to perform an operation on all instances of a struct defined in a given package. In order to do that, I have contemplated developping a function that gather those instances. But I haven't found anything yet.
To clarify my goal (following '@Muffin Top' and '@Volker' answer), I currently do this registration manualy into a pointer store present in each package. There are two problems with this approach, the registration is a mundane task and it is error prone.
To make my case clear, consider a package foo
with one struct Foo
. Foo
has one string
field Name
. The package also defines two instances of Foo
declared as Foo1
& Foo2
package foo
type Foo struct {
Name string
}
var Foo1, Foo2 = Foo{Name: "Foo1"}, Foo{Name: "Foo2"}
The GetInstancesOfPkg
I am trying to implement would be called like in the below example. The operation to perform is just to print the Name
field.
This is a working example but with a mockup version of 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
}
For the solution, I know there is no such function in the reflect
standard library or any other library I know of. However, I was contemplating :
an algorithm that parses the entire program memory, identify each variable, get its type and gather those that match the struct type of the package. Since delve and heapdump do parse the entire memory and that delve can guess the variable type, I have a hunch that my desired function could be implemented. I have been trying to see how delve is doing or how heapcoredump is developped but this is a too big piece of knowledge to swallow for the desired goal.
an alternative would be to add a pre-compilation step that modifies the abstract syntax tree (AST) by adding the registration each time there is a a variable initialisation.
I am not even sure if this level of reflexion is possible with go (or if it is portable ?)
Performance is not an issue, the program could be compiled with wathever flag necessary or the entire memory could be parsed.
No.
You must redesign, e.g. by allocating the instances through a function which memorizes them.