0

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.
 }
James Sapam
  • 16,036
  • 12
  • 50
  • 73
  • Related: [Call all functions with special prefix or suffix in Golang](https://stackoverflow.com/questions/37384473/call-all-functions-with-special-prefix-or-suffix-in-golang/37384665#37384665). – icza Jul 13 '17 at 07:05
  • Thank you @icza, that is useful. – James Sapam Jul 13 '17 at 23:54

1 Answers1

3

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
    }
}
jeevatkm
  • 4,571
  • 1
  • 23
  • 24
  • Thanks for your response, but my sliceOfCollector is slice of string name. Is there any way to do from name? – James Sapam Jul 12 '17 at 23:22
  • It is not possible to create from string name, you need a `type`. Otherwise as an alternative, you may have to follow factory pattern sort of; supply string to function and have `switch/if` then create a instance normally `package1.NewRule{}` then return it. – jeevatkm Jul 12 '17 at 23:26
  • Okk. let me try – James Sapam Jul 12 '17 at 23:34
  • Shall I add the example of that in the answer? let me know. – jeevatkm Jul 12 '17 at 23:34