包选择器与字符串名称

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

Package selector with string name

问题

我正在尝试找出一种方法来从多个包中访问具有名称的结构体。

这是我的结构体:

  1. collector/package1
  2. collector/package2

..
package1 包含:

  1. package collector
  2. type NewRule struct {
  3. }

..
package2 包含:

  1. package collector
  2. type OldRule struct {
  3. }

....

在我的 main.go 文件中:

  1. import "github.com/mypackage/collector"
  2. sliceOfCollector := []string{"NewRule", "OldRule"}
  3. for _, col := range sliceOfCollector{
  4. // 如何使用上述 collector 名称 `col` 创建结构体实例。
  5. }
英文:

I am trying to figure out a way to access struct from multiple packages with name.

Here is my structure:

  1. collector/package1
  2. collector/package2

..
package1 contains:

  1. package collector
  2. type NewRule struct {
  3. }

..
package2 contains:

  1. package collector
  2. type OldRule struct {
  3. }

....

In my main.go:

  1. import "github.com/mypackage/collector"
  2. sliceOfCollector := []string{"NewRule", "OldRule"}
  3. for _, col := range sliceOfCollector{
  4. // How to use the above collector name `col` to create struct instance.
  5. }

答案1

得分: 3

使用reflect.Newstruct类型。在Go语言中,你必须使用类型来动态创建一个新的实例,而不是字符串。

示例:要动态创建结构体实例,可以这样做:

  1. package main
  2. import "reflect"
  3. import (
  4. "github.com/collector/package1"
  5. "github.com/collector/package2"
  6. )
  7. func main() {
  8. sliceOfCollector := make([]reflect.Type, 0)
  9. sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package1.NewRule)(nil)).Elem())
  10. sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package2.OldRule)(nil)).Elem())
  11. for _, collectorType := range sliceOfCollector {
  12. col := reflect.New(collectorType)
  13. fmt.Printf("%#v\n", col)
  14. }
  15. }

之后,你可以使用type assertions,如col.Interface().(*package1.NewRule)


编辑:

在评论互动之后,添加了以下内容。

使用工厂方法创建实例,这只是一个想法。

  1. func main() {
  2. sliceOfCollector := []string{"NewRule", "OldRule"}
  3. for _, col := range sliceOfCollector {
  4. rule := CreateRuleByName(col)
  5. fmt.Printf("%#v\n", rule)
  6. }
  7. }
  8. func CreateRuleByName(name string) interface{} {
  9. switch name {
  10. case "NewRule":
  11. return &package1.NewRule{}
  12. case "OldRule":
  13. return &package2.OldRule{}
  14. default:
  15. return nil
  16. }
  17. }
英文:

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

  1. package main
  2. import "reflect"
  3. import (
  4. "github.com/collector/package1"
  5. "github.com/collector/package2"
  6. )
  7. func main() {
  8. sliceOfCollector := make([]reflect.Type, 0)
  9. sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package1.NewRule)(nil)).Elem()})
  10. sliceOfCollector = append(sliceOfCollector, reflect.TypeOf((*package2.OldRule)(nil)).Elem()})
  11. for _, collectorType := range slice sliceOfCollector {
  12. col := reflect.New(collectorType)
  13. fmt.Printf("%#v\n", col)
  14. }
  15. }

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.

  1. func main() {
  2. sliceOfCollector := []string{"NewRule", "OldRule"}
  3. for _, col := range sliceOfCollector {
  4. rule := CreateRuleByName(col)
  5. fmt.Printf("%#v\n", rule)
  6. }
  7. }
  8. func CreateRuleByName(name string) interface{} {
  9. switch name {
  10. case "NewRule":
  11. return &package1.NewRule{}
  12. case "OldRule":
  13. return &package2.OldRule{}
  14. default:
  15. return nil
  16. }
  17. }

huangapple
  • 本文由 发表于 2017年7月13日 06:42:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/45068666.html
匿名

发表评论

匿名网友

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

确定