【问题标题】:Convert interface{} to *[]int in golang在 golang 中将 interface{} 转换为 *[]int
【发布时间】:2014-12-30 14:32:28
【问题描述】:

我收到一个基本上是切片的接口。现在我想将它转换为指向切片的指针。问题是,我要么有切片本身,要么有一个指向接口的指针。 我可以在代码示例中轻松展示:

func main(){
    model := []int{1,2,3,4,5,6,7,8,10,11,133123123123}
    method(model)
}

func method(model interface{}){ 
    fmt.Println(reflect.TypeOf(model))    // this is of type []int
    fmt.Println(reflect.TypeOf(&model))   // this is of type *interface{}
}

我需要的是这种类型:

fmt.Println(reflect.TypeOf(result))    // this should be type *[]int

我只在运行时知道类型,因此我不能只接受 &(model.([]int))

有没有办法使用 golang 反射来接收这个? 'int' 类型在这里实际上并不重要,重要的是,它是一个指向切片的指针*[]interface{} 也可以。

编辑:
为了使问题更清楚,我应该补充一点:我对切片的数据不感兴趣,而只对获取指向相同类型切片的指针(基本上可以为空)感兴趣。因此,James Henstridge 的答案非常有效。

【问题讨论】:

  • golang.org/pkg/reflect/#Value.Addr 有什么问题?我承认我不明白你真正想做什么。这真的取决于。并非 Go 中的所有值 都是 可寻址的,因此可能无法做到。你想用 *[]int 做什么?
  • 确实这个值是不可寻址的。基本上我想创建一个预定义类型的切片(使用reflect.MakeSlice)并将其传递给mgo 库的一个方法(mgo 的Query 的All() 方法)。此方法需要一个 Ptr 来切片。我通过在已知类型的外部创建切片找到了解决方案。但我正试图找到一种在内部以通用方式执行此操作的方法。我是否理解正确,因为它不是一个可寻址的值,所以不可能这样做?
  • everything 在 go 中是按值传递的。将值复制到 method 调用后,您无法获得指向 model 的指针。不管是不是interface{},你都有切片值,而不是指针。
  • 要添加到 JimB 的注释中,切片 act 就像指针一样,因为它们引用了一些内存块,并且更改切片的元素会更改内存,因此您可以在调用者中看到它, 但 切片变量本身 不能更改,因为 THAT 作为值传递。 slice 变量包含一个指向底层内存的指针以及 slice 的长度和容量。

标签: reflection go slice


【解决方案1】:

在尝试回答这个问题之前,有必要退后一步,问一下您所追求的*[]int 值应该指向什么?

鉴于method 的调用方式,我们不可能从调用上下文中获得指向model 变量的指针,因为它只会接收切片的副本作为其参数(请注意,这是一个副本切片头的:后备数组是共享的)。

我们也无法获得作为参数传递的副本的指针,因为它被存储为interface{} 变量:接口变量拥有用于存储其动态值的内存,并且在为其分配了一个新值。如果您可以使用指向动态值的指针,那么如果分配了不同的类型,则会破坏类型安全。

如果我们制作切片的第三份副本,我们可以获得*[]int 指针,但不清楚这是否是您所需要的:

v := reflect.New(reflect.TypeOf(model))
v.Elem().Set(reflect.ValueOf(model))
result := v.Interface()

这本质上是一种与类型无关的写法:

v := new([]int)
*v = model
var result interface{} = v

现在,如果您确实需要在调用上下文中指向切片变量的指针,则需要确保使用指向切片的指针调用 method 并采取相应措施。

【讨论】:

  • 这是反射包的一个很好的用途。
  • 谢谢,这完美!我基本上对切片数组的内容不感兴趣(在我的用例中它总是空的),而只对获取相同类型的切片和指向它的指针感兴趣。
猜你喜欢
  • 2017-10-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-17
  • 2018-07-04
  • 2019-09-22
  • 1970-01-01
相关资源
最近更新 更多