如何获取界面内的值的地址?
我有一个存储在接口中的结构,在list.List元素中:
import "container/list"
type retry struct{}
p := &el.Value.(retry)
但我明白了:
cannot take the address of el.Value.(retry)
发生了什么事?由于struct存储在接口中,为什么我不能获得指向它的指针?
答案 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
}
来自评论:
请注意,这是指向值副本的指针,而不是指向值本身的指针。
因此解决问题的方法很简单;在接口中存储指针,而不是值。
答案 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)
}
对于类型为T的操作数x,地址操作& x生成a 类型* T到x的指针。操作数必须是可寻址的,即 变量,指针间接或切片索引操作; 或可寻址结构操作数的字段选择器;或数组 可寻址数组的索引操作。作为例外 可寻址性要求,x也可以是复合文字。
参考文献: