用(相对)未知/任意方法扩展结构,进行反射(或避免反射)

时间:2014-08-28 13:03:51

标签: reflection struct go

以下显然不起作用:

Arbitrary := struct {
    field1 string
    field2 string
}{"a", "b"}

fmap := make(map[string]func(string) string)
fmap["fone"] = func(s string) string { fmt.Printf("function fone: %s", s) }
fmap["ftwo"] = func(s string) string { fmt.Printf("function ftwo: %s", s) }

// probably ok, as simple examples go, to this point where reflection needs to be used
// the below does not work 
Arbitrary.fone = fmap["fone"]

Arbitrary.fone("hello")

以上是我尝试做的核心:创建一个带有值的结构,然后从函数映射或传入的函数创建结构上的方法。基本上我有一个数据结构&安培;在创建类型之前需要使用未知方法扩展的模糊行为。

我正在寻找明显的&不可避免:

  1. 如何在Go

  2. 中执行此操作
  3. 为什么不应该这样做,或者不能在Go中完成(它可以通过反射包,我只是找不到例子或推理它)< / p>

  4. 如何在Go中完成此操作(某种界面构造我完全没有想到。我已经尝试了一个可以处理行为的界面;但它并没有可以添加其他行为的帐户,至少我还没有完全了解界面使用情况,这是问题的一部分)

  5. 如果你是一个需要复杂性here is the start of the actual task I'm trying to accomplish的人,那么结构行为可以扩展。

1 个答案:

答案 0 :(得分:1)

我完全误解了这个问题。

不,你不能凭空创造一个新的结构,并为它分配字段,即使你可以,因为对所有圣洁的爱,不要那样做

您可以使用多个接口,例如:

type Base interface {
    Id() int //all structs must implement this
}
type Foo interface {
    Base
    Foo()
}
type Bar interface {
    Base
    Bar()
}

然后创建一个map[string]Base,然后您可以稍后断言该值。

//将原始答案留作问题的不同方法。

虽然通常使用反射来完成这种事情,但是如果你接受了有限数量的回调&#34;&#34;你可以使用类型断言和interface{}映射,不需要反射。

var ctx = &Ctx{"Hello"}
var funcs = map[string]interface{}{
    "m3": ctx.Do,
    "m4": func(c *Ctx) { fmt.Println("ctx:", c) },
}

type Ctx struct {
    Name string
}

func (c *Ctx) Do() {
    fmt.Printf("Do: %+v\n", c)
}

func call(m string) {
    if f, ok := funcs[m]; ok {
        switch fn := f.(type) {
        case func():
            fn()
        case func(*Ctx):
            fn(&Ctx{"Hello world"})
        default:
            panic(fn)
        }
    }
}

playground