获取接口内的值的地址

时间:2013-03-20 08:50:23

标签: pointers interface go memory-address

如何获取界面内的值的地址?

我有一个存储在接口中的结构,在list.List元素中:

import "container/list"
type retry struct{}
p := &el.Value.(retry)

但我明白了:

cannot take the address of el.Value.(retry)

发生了什么事?由于struct存储在接口中,为什么我不能获得指向它的指针?

4 个答案:

答案 0 :(得分:6)

要理解为什么这是不可能的,考虑接口变量实际上是什么是有帮助的。接口值占用两个单词,第一个描述所包含值的类型,第二个是(a)保持包含的值(如果它适合单词)或(b)指向存储的值(如果该值不适合单词)。

需要注意的重要事项是:(1)包含的值属于接口变量,(2)当为变量赋值新值时,可以重用该值的存储。知道这一点,请考虑以下代码:

var v interface{}
v = int(42)
p := GetPointerToInterfaceValue(&v) // a pointer to an integer holding 42
v = &SomeStruct{...}

现在已经重用了整数的存储来保存指针,*p现在是该指针的整数表示。您可以看到它如何具有破坏类型系统的能力,因此Go没有提供这样做的方法(在使用unsafe包之外)。

如果需要指向存储在列表中的结构的指针,那么一个选项是存储指向列表中结构的指针而不是直接存储结构值。或者,您可以将*list.Element值作为对包含结构的引用传递。

答案 1 :(得分:2)

在第一个近似中:你做不到。即使你可以,p本身也必须有interface{}类型并且不会太有帮助 - 你不能直接取消引用它。

强制性问题是:你想解决什么问题?

最后但并非最不重要:接口定义行为而不是结构。直接使用接口的底层实现类型通常会破坏接口契约,尽管可能存在非常规的合法案例。但是type switch statement已经为一组有限的静态类型提供了服务。

答案 2 :(得分:2)

类型断言是一个导致两个值的表达式。在这种情况下采取地址是不明确的。

p, ok := el.Value.(retry)
if ok {
    // type assertion successful
    // now we can take the address
    q := &p 
}

来自评论:

  

请注意,这是指向值副本的指针,而不是指向值本身的指针。

     

- James Henstridge

因此解决问题的方法很简单;在接口中存储指针,而不是值。

答案 3 :(得分:2)

  

Get pointer to interface value?

     

给定一个接口类型的变量,有没有办法得到一个   指向存储在变量?

中的值的指针      

这是不可能的。

     

Rob Pike

接口值不一定是可寻址的。例如,

package main

import "fmt"

func main() {
    var i interface{}
    i = 42
    // cannot take the address of i.(int)
    j := &i.(int)
    fmt.Println(i, j)
}
  

Address operators

     

对于类型为T的操作数x,地址操作& x生成a   类型* T到x的指针。操作数必须是可寻址的,即   变量,指针间接或切片索引操作;   或可寻址结构操作数的字段选择器;或数组   可寻址数组的索引操作。作为例外   可寻址性要求,x也可以是复合文字。

参考文献:

Interface types

Type assertions

Go Data Structures: Interfaces

Go Interfaces