我如何编写单个函数来处理不同类型的函数

时间:2014-10-12 22:52:33

标签: reflection go

鉴于以下示例,无论如何可以创建一个能够逐字地再现(不仅仅是使用reflect.Type)进一步操作的实际类型的函数吗?我知道go是静态类型的,虽然我可以将任何结构传递给定义接口参数的函数非常酷,但是我有可能在其他方面做得更多吗?

我已经查看了反射包,但只找到了返回reflect.Type或reflect.Value的东西。我使用New()方法返回一个新的reflect.Value - 在那里我无法设置任何字段。也许有经验的反射包可以告诉我这是否可能 - 或者是否有另一种方法可以做到。

package main

import "fmt"

type User struct {
    Name string
}

func main() {
    user := User{Name:"FooBar"}
    DoSomethingGenericWithStruct(user)
}

func DoSomethingGenericWithStruct(i interface{}) {
    // access fields of i ...
    // or create slice of type of i ([]User) ...
    // or instantiate new object of type of i (new User) ...
    // ...
}

1 个答案:

答案 0 :(得分:2)

您必须将指针传递给您的结构才能修改它。

另请注意,使用反射具有较高的运行时性能成本。

func DoSomethingGenericWithStruct(i interface{}) {
    val := reflect.ValueOf(i)
    if val.Kind() != reflect.Ptr {
        panic("need a pointer")
    }
    val = val.Elem() // now you can modify it
    // add error checking and such, this will panic if it's not a struct or there's no "Name" field
    val.FieldByName("Name").SetString("stuff")
}

playground

创建新元素并指定它:

val = val.Elem()
nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
nval.FieldByName("Name").SetString("stuff") 
val.Set(nval)

修改实际的结构,而不是reflect.Value,你必须得到它interface{}然后断言它到你的类型,例如:

nval := reflect.New(val.Type()).Elem() // create a new struct of the same type
user := nval.Interface().(User)
user.Name = "Stuff"
val.Set(reflect.ValueOf(user))