英文:
How to instantiate struct that is defined in different package from struct name and provide fields
问题
假设我在pkg
包中定义了一些struct
:
package pkg
type Foo struct {
FieldA string
FieldB string
}
type Bar struct {
FieldA string
FieldB string
}
func (Foo) Show() {
fmt.Println("Foo")
}
func (Bar) Show() {
fmt.Println("Bar")
}
type Showable interface {
Show()
}
Registry := map[string]Showable{
"Foo": Foo,
"Bar": Bar,
}
我想要动态实例化这些struct
,类似于这样:
package main
import "url/user/pkg"
func main() {
foo := pkg.Registry["Foo"]{
FieldA: "A",
FieldB: "B",
}
bar := pkg.Registry["Bar"]{
FieldA: "X",
FieldB: "Y",
}
foo.Show()
bar.Show()
}
上述代码显然无法工作。
是否有可能实现这个目标?我对Go语言还不熟悉。我已经看过reflect
,尝试使用指针、空实例的指针来构建Registry
,但是无法找到解决方法。
最终,我想要编写一个命令行实用程序来更改某些程序的主题。我已经编写了特定于程序的方法(类似上面示例中的Show
方法),并尝试从config.json
文件中读取程序特定的参数,并动态创建实例。
英文:
Suppose I have some struct
s defined in package pkg
:
package pkg
type Foo struct {
FieldA string
FieldB string
}
type Bar struct {
FieldA string
FieldB string
}
func (Foo) Show() {
fmt.Println("Foo")
}
func (Bar) Show() {
fmt.Println("Bar")
}
type Showable interface {
Show()
}
Registry := map[string]Showable{
//not sure about value type^
"Foo": Foo, // staticcheck shows: not a type
"Bar": Bar, //
}
And I want to instantiate the struct
s dynamically; something like this:
package main
import "url/user/pkg"
func main() {
foo := pkg.Registry["Foo"]{
FieldA: "A",
FieldB: "B",
}
bar := pkg.Registry["Bar"]{
FieldA: "X",
FieldB: "Y",
}
foo.Show()
bar.Show()
}
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
:
package pkg
import (
"fmt"
"io"
)
type NewShowable func(r io.Reader) Showable
type Showable interface {
Show()
}
type Foo struct {
FieldA string
FieldB string
}
func newFoo(r io.Reader) Showable {
// 从 r 中读取配置并构造 Foo
return Foo{}
}
func (Foo) Show() {
fmt.Println("Foo")
}
type Bar struct {
FieldA string
FieldB string
}
func newBar(r io.Reader) Showable {
// 从 r 中读取配置并构造 Bar
return Bar{}
}
func (Bar) Show() {
fmt.Println("Bar")
}
var Registry = map[string]NewShowable{
"Foo": newFoo,
"Bar": newBar,
}
main.go
:
package main
import (
"log"
"os"
"url/user/pkg"
)
func main() {
f, err := os.Open("config.json")
if err != nil {
log.Fatalln(err)
}
defer f.Close()
foo := pkg.Registry["Foo"](f)
f2, err := os.Open("config2.json")
if err != nil {
log.Fatalln(err)
}
defer f2.Close()
bar := pkg.Registry["Bar"](f2)
foo.Show()
bar.Show()
}
英文:
If I correctly understand what you are trying to achieve, here is
the way to do that:
registry.go
:
package pkg
import (
"fmt"
"io"
)
type NewShowable func(r io.Reader) Showable
type Showable interface {
Show()
}
type Foo struct {
FieldA string
FieldB string
}
func newFoo(r io.Reader) Showable {
// Read config from r and construct Foo
return Foo{}
}
func (Foo) Show() {
fmt.Println("Foo")
}
type Bar struct {
FieldA string
FieldB string
}
func newBar(r io.Reader) Showable {
// Read config from r and construct Bar
return Bar{}
}
func (Bar) Show() {
fmt.Println("Bar")
}
var Registry = map[string]NewShowable{
"Foo": newFoo,
"Bar": newBar,
}
main.go
:
package main
import (
"log"
"os"
"url/user/pkg"
)
func main() {
f, err := os.Open("config.json")
if err != nil {
log.Fatalln(err)
}
defer f.Close()
foo := pkg.Registry["Foo"](f)
f2, err := os.Open("config2.json")
if err != nil {
log.Fatalln(err)
}
defer f2.Close()
bar := pkg.Registry["Bar"](f2)
foo.Show()
bar.Show()
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论