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

Reflection 如何编写单个函数来处理不同的类型,reflection,go,Reflection,Go,给出下面的示例,是否有可能创建一个函数,该函数可以直接复制(而不仅仅是获取reflect.Type)实际类型以供进一步操作?我知道go是静态类型的,虽然我可以将任何结构传递给定义接口参数的函数非常酷,但我有没有可能通过其他方式做更多的工作 我已经查看了reflect包,但只找到了返回reflect.Type或reflect.Value的内容。我使用了New()方法,该方法返回了一个新的reflect.Value——在那里我无法设置任何字段。也许有经验的reflect软件包的人可以告诉我这是否确实

给出下面的示例,是否有可能创建一个函数,该函数可以直接复制(而不仅仅是获取reflect.Type)实际类型以供进一步操作?我知道go是静态类型的,虽然我可以将任何结构传递给定义接口参数的函数非常酷,但我有没有可能通过其他方式做更多的工作

我已经查看了reflect包,但只找到了返回reflect.Type或reflect.Value的内容。我使用了New()方法,该方法返回了一个新的reflect.Value——在那里我无法设置任何字段。也许有经验的reflect软件包的人可以告诉我这是否确实可行,或者是否有其他方法可以做到这一点

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) ...
    // ...
}

您必须传递指向结构的指针才能修改它

还要记住,使用反射会带来很高的运行时性能成本

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")
}

要创建新元素并将其指定,请执行以下操作:

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
,您必须将
接口{}
添加到它,然后将其断言到您的类型,例如:

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))

众所周知,Golang缺少参数类型和泛型函数。你可能会看到,甚至是从中获得灵感。这个问题被否决的原因是什么?所以基本上我永远不会得到一个真正的用户对象,而是一个反射对象?就像我永远不能做
nval.Name=“stuff”
?@skripted你可以,我添加了另一个例子。太棒了,谢谢你!所以我真的需要事先知道类型并断言它,该死的。太遗憾了,没有办法做
user:=nval.Interface()(reflect.TypeOf(i))
@skripted如果你真的需要该功能,你可能想重新考虑你正在尝试做什么,或者Go是否是你项目的工具。我认为Go是正确的工具,我只是可能在错误的问题上使用了错误的功能。我想我会重新考虑我的申请如何运作。