包选择器与字符串名称

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

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.Newstruct类型。在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
    }
}

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:

确定