【问题标题】:How I can write a single function to work with different types我如何编写一个函数来处理不同的类型
【发布时间】:2014-10-12 22:52:33
【问题描述】:

鉴于以下示例,是否有可能创建一个函数,可以从字面上复制(不仅获取反射.Type)实际类型以进行进一步操作?我知道 go 是静态类型的,虽然我可以将任何结构传递给定义接口参数的函数非常酷,但我是否有机会做更多相反的事情?

我已经查看了 reflect 包,但只找到了返回 reflect.Type 或 reflect.Value 的东西。我使用了返回一个新的 reflect.Value 的 New() 方法——我无法设置任何字段。也许有使用反射包经验的人可以告诉我这是否绝对可行 - 或者是否有其他方法。

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

【问题讨论】:

标签: reflection go


【解决方案1】:

你必须传递一个指向你的结构的指针才能修改它。

另外请记住,使用反射具有很高的运行时性能成本。

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

【讨论】:

  • 所以基本上我永远不会得到一个真正的用户对象,而总是一个反射对象?就像我永远无法做到nval.Name = "stuff"
  • @skripted 你可以,我添加了另一个例子。
  • 太棒了,谢谢!所以我真的需要事先知道类型并断言它,该死的。太伤心了没办法user := nval.Interface().( reflect.TypeOf(i) )
  • @skripted 你可能想重新考虑你正在尝试做什么,或者如果你真的需要这个功能,Go 是否是你项目的工具。
  • 我认为 Go 是正确的工具,我只是可能为错误的问题使用了错误的功能。我想我会重新考虑我的应用程序是如何工作的。
猜你喜欢
  • 1970-01-01
  • 2019-09-17
  • 1970-01-01
  • 1970-01-01
  • 2016-07-07
  • 1970-01-01
  • 2016-03-28
  • 2010-09-15
  • 1970-01-01
相关资源
最近更新 更多