How to instantiate struct that is defined in different package from struct name and provide fields

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

How to instantiate struct that is defined in different package from struct name and provide fields

问题

假设我在pkg包中定义了一些struct

  1. package pkg
  2. type Foo struct {
  3. FieldA string
  4. FieldB string
  5. }
  6. type Bar struct {
  7. FieldA string
  8. FieldB string
  9. }
  10. func (Foo) Show() {
  11. fmt.Println("Foo")
  12. }
  13. func (Bar) Show() {
  14. fmt.Println("Bar")
  15. }
  16. type Showable interface {
  17. Show()
  18. }
  19. Registry := map[string]Showable{
  20. "Foo": Foo,
  21. "Bar": Bar,
  22. }

我想要动态实例化这些struct,类似于这样:

  1. package main
  2. import "url/user/pkg"
  3. func main() {
  4. foo := pkg.Registry["Foo"]{
  5. FieldA: "A",
  6. FieldB: "B",
  7. }
  8. bar := pkg.Registry["Bar"]{
  9. FieldA: "X",
  10. FieldB: "Y",
  11. }
  12. foo.Show()
  13. bar.Show()
  14. }

上述代码显然无法工作。

是否有可能实现这个目标?我对Go语言还不熟悉。我已经看过reflect,尝试使用指针、空实例的指针来构建Registry,但是无法找到解决方法。

最终,我想要编写一个命令行实用程序来更改某些程序的主题。我已经编写了特定于程序的方法(类似上面示例中的Show方法),并尝试从config.json文件中读取程序特定的参数,并动态创建实例。

英文:

Suppose I have some structs defined in package pkg:

  1. package pkg
  2. type Foo struct {
  3. FieldA string
  4. FieldB string
  5. }
  6. type Bar struct {
  7. FieldA string
  8. FieldB string
  9. }
  10. func (Foo) Show() {
  11. fmt.Println("Foo")
  12. }
  13. func (Bar) Show() {
  14. fmt.Println("Bar")
  15. }
  16. type Showable interface {
  17. Show()
  18. }
  19. Registry := map[string]Showable{
  20. //not sure about value type^
  21. "Foo": Foo, // staticcheck shows: not a type
  22. "Bar": Bar, //
  23. }

And I want to instantiate the structs dynamically; something like this:

  1. package main
  2. import "url/user/pkg"
  3. func main() {
  4. foo := pkg.Registry["Foo"]{
  5. FieldA: "A",
  6. FieldB: "B",
  7. }
  8. bar := pkg.Registry["Bar"]{
  9. FieldA: "X",
  10. FieldB: "Y",
  11. }
  12. foo.Show()
  13. bar.Show()
  14. }

The above clearly doesn't work.

Is it possible to achieve this? I am new to [tag:go]. I have looked at reflect, I have tried to build the Registry with pointers, pointers of empty instance, but couldn't figure out a way to do this.

Ultimately, I am trying to write a command line utility to change themes of certain programs. I have written program specific methods (like Show in above example), and I am trying to read the program specific params from a config.json file, and create the instances dynamically.

答案1

得分: 2

如果我正确理解你想要实现的内容,以下是实现的方法:

registry.go:

  1. package pkg
  2. import (
  3. "fmt"
  4. "io"
  5. )
  6. type NewShowable func(r io.Reader) Showable
  7. type Showable interface {
  8. Show()
  9. }
  10. type Foo struct {
  11. FieldA string
  12. FieldB string
  13. }
  14. func newFoo(r io.Reader) Showable {
  15. // 从 r 中读取配置并构造 Foo
  16. return Foo{}
  17. }
  18. func (Foo) Show() {
  19. fmt.Println("Foo")
  20. }
  21. type Bar struct {
  22. FieldA string
  23. FieldB string
  24. }
  25. func newBar(r io.Reader) Showable {
  26. // 从 r 中读取配置并构造 Bar
  27. return Bar{}
  28. }
  29. func (Bar) Show() {
  30. fmt.Println("Bar")
  31. }
  32. var Registry = map[string]NewShowable{
  33. "Foo": newFoo,
  34. "Bar": newBar,
  35. }

main.go:

  1. package main
  2. import (
  3. "log"
  4. "os"
  5. "url/user/pkg"
  6. )
  7. func main() {
  8. f, err := os.Open("config.json")
  9. if err != nil {
  10. log.Fatalln(err)
  11. }
  12. defer f.Close()
  13. foo := pkg.Registry["Foo"](f)
  14. f2, err := os.Open("config2.json")
  15. if err != nil {
  16. log.Fatalln(err)
  17. }
  18. defer f2.Close()
  19. bar := pkg.Registry["Bar"](f2)
  20. foo.Show()
  21. bar.Show()
  22. }
英文:

If I correctly understand what you are trying to achieve, here is
the way to do that:

registry.go:

  1. package pkg
  2. import (
  3. "fmt"
  4. "io"
  5. )
  6. type NewShowable func(r io.Reader) Showable
  7. type Showable interface {
  8. Show()
  9. }
  10. type Foo struct {
  11. FieldA string
  12. FieldB string
  13. }
  14. func newFoo(r io.Reader) Showable {
  15. // Read config from r and construct Foo
  16. return Foo{}
  17. }
  18. func (Foo) Show() {
  19. fmt.Println("Foo")
  20. }
  21. type Bar struct {
  22. FieldA string
  23. FieldB string
  24. }
  25. func newBar(r io.Reader) Showable {
  26. // Read config from r and construct Bar
  27. return Bar{}
  28. }
  29. func (Bar) Show() {
  30. fmt.Println("Bar")
  31. }
  32. var Registry = map[string]NewShowable{
  33. "Foo": newFoo,
  34. "Bar": newBar,
  35. }

main.go:

  1. package main
  2. import (
  3. "log"
  4. "os"
  5. "url/user/pkg"
  6. )
  7. func main() {
  8. f, err := os.Open("config.json")
  9. if err != nil {
  10. log.Fatalln(err)
  11. }
  12. defer f.Close()
  13. foo := pkg.Registry["Foo"](f)
  14. f2, err := os.Open("config2.json")
  15. if err != nil {
  16. log.Fatalln(err)
  17. }
  18. defer f2.Close()
  19. bar := pkg.Registry["Bar"](f2)
  20. foo.Show()
  21. bar.Show()
  22. }

huangapple
  • 本文由 发表于 2021年12月31日 14:21:00
  • 转载请务必保留本文链接:https://go.coder-hub.com/70539550.html
匿名

发表评论

匿名网友

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

确定