英文:
Package selector with string name
问题
我正在尝试找出一种方法来从多个包中访问具有名称的结构体。
这是我的结构体:
collector/package1
collector/package2
..
package1 包含:
package collector
type NewRule struct {
}
..
package2 包含:
package collector
type OldRule struct {
}
....
在我的 main.go 文件中:
import "github.com/mypackage/collector"
sliceOfCollector := []string{"NewRule", "OldRule"}
for _, col := range sliceOfCollector{
// 如何使用上述 collector 名称 `col` 创建结构体实例。
}
英文:
I am trying to figure out a way to access struct from multiple packages with name.
Here is my structure:
collector/package1
collector/package2
..
package1 contains:
package collector
type NewRule struct {
}
..
package2 contains:
package collector
type OldRule struct {
}
....
In my main.go:
import "github.com/mypackage/collector"
sliceOfCollector := []string{"NewRule", "OldRule"}
for _, col := range sliceOfCollector{
// How to use the above collector name `col` to create struct instance.
}
答案1
得分: 3
使用reflect.New
和struct
类型。在Go语言中,你必须使用类型来动态创建一个新的实例,而不是字符串。
示例:要动态创建结构体实例,可以这样做:
package main
import "reflect"
import (
"github.com/collector/package1"
"github.com/collector/package2"
)
func main() {
sliceOfCollector := make([]reflect.Type, 0)
sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package1.NewRule)(nil)).Elem())
sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package2.OldRule)(nil)).Elem())
for _, collectorType := range sliceOfCollector {
col := reflect.New(collectorType)
fmt.Printf("%#v\n", col)
}
}
之后,你可以使用type assertions,如col.Interface().(*package1.NewRule)
。
编辑:
在评论互动之后,添加了以下内容。
使用工厂方法创建实例,这只是一个想法。
func main() {
sliceOfCollector := []string{"NewRule", "OldRule"}
for _, col := range sliceOfCollector {
rule := CreateRuleByName(col)
fmt.Printf("%#v\n", rule)
}
}
func CreateRuleByName(name string) interface{} {
switch name {
case "NewRule":
return &package1.NewRule{}
case "OldRule":
return &package2.OldRule{}
default:
return nil
}
}
英文:
Use reflect.New with struct
type. In Go you have to use type to create a new instance dynamically not string.
Example: To create struct instance dynamically, you can do
package main
import "reflect"
import (
"github.com/collector/package1"
"github.com/collector/package2"
)
func main() {
sliceOfCollector := make([]reflect.Type, 0)
sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package1.NewRule)(nil)).Elem()})
sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package2.OldRule)(nil)).Elem()})
for _, collectorType := range slice sliceOfCollector {
col := reflect.New(collectorType)
fmt.Printf("%#v\n", col)
}
}
You can use type assertions after that col.Interface().(*package1.NewRule)
EDIT:
After comment interaction, added following.
Creating a instance using factory method. Just an idea.
func main() {
sliceOfCollector := []string{"NewRule", "OldRule"}
for _, col := range sliceOfCollector {
rule := CreateRuleByName(col)
fmt.Printf("%#v\n", rule)
}
}
func CreateRuleByName(name string) interface{} {
switch name {
case "NewRule":
return &package1.NewRule{}
case "OldRule":
return &package2.OldRule{}
default:
return nil
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论