【问题标题】:Is there a way in go to dynamicaly gather instances of a given struct type?有没有办法动态收集给定结构类型的实例?
【发布时间】:2021-01-19 06:27:41
【问题描述】:

我想在程序的任何阶段对给定包中定义的结构的所有实例执行操作。为了做到这一点,我已经考虑开发一个收集这些实例的函数。但我还没有找到任何东西。

为了阐明我的目标(遵循“@Muffin Top”和“@Volker”的回答),我目前手动将此注册到每个包中存在的指针存储中。这种方法有两个问题,注册是一项普通的任务,而且容易出错。

为了说明我的情况,考虑一个包foo 和一个结构FooFoo 有一个string 字段Name。该包还定义了Foo 的两个实例,声明为Foo1Foo2

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 标志编译程序,或者可以解析整个内存。

【问题讨论】:

  • Go 标准库不提供枚举给定类型值的方法。你试图解决的更高层次的问题是什么?可能有办法编写一些应用程序代码来解决这个问题。
  • 这个更高级别的问题是,目前,我在 pkg 存储中手动注册所有实例
  • 请注意,即使是垃圾收集器也可能永远看不到某些类型的某些实例。只有编译器自己知道。就可移植性和可靠性而言,您使用预编译步骤的想法是最有希望的。
  • @torek,感谢您对 GC 的见解。我将尝试预编译步骤,看到生成的代码会很有趣。

标签: go reflection garbage-collection delve


【解决方案1】:

有没有办法动态地收集给定结构类型的实例?

没有。

您必须重新设计,例如通过存储实例的函数分配实例。

【讨论】:

  • 这个更高级别的问题是,目前,我在 pkg 存储中手动注册所有实例。我更新了问题以澄清。
  • 你的意思是,即使我非常有说服力地深入研究,我也无法编写运行时内存分析器?
  • 感谢您的回答。我想知道 Go 是否为我的请求提供了理论基础,答案是否定的。我预计会有相当大的黑客/努力来实现它。
  • 嗨@Volker,另一个我忘记提到的关于通过函数分配实例的问题(例如func NewFoo() *foo.Foo是一些变量是在包中静态定义的(如上面的示例)在编译时有很多参数。我不知道如何使用NewFoo() 函数来做到这一点。
  • 嗨@Volker,感谢您让我知道什么是 XY 问题。在这种情况下,X 如下所示:我的客户希望将他的业务逻辑写在一个不依赖于 ORM 的包中,或者需要手动注册他的实例。但是,在某个阶段,我想注册为将它们放入数据库而创建的实例。我看不到我可以在这里重新设计什么,但忘记了我的客户要求。
猜你喜欢
  • 1970-01-01
  • 2021-07-10
  • 1970-01-01
  • 1970-01-01
  • 2022-06-21
  • 1970-01-01
  • 2010-11-27
  • 2011-08-03
  • 1970-01-01
相关资源
最近更新 更多