7

インターフェイス内の値のアドレスを取得するにはどうすればよいですか?

インターフェイスの list.List 要素に格納された構造体があります。

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

しかし、私はこれを取得します:

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

どうしたの?構造体はインターフェイスに格納されているため、構造体へのポインターを取得できないのはなぜですか?

4

4 に答える 4

9

これが不可能な理由を理解するには、インターフェイス変数が実際に何であるかを考えると役に立ちます。インターフェイス値は 2 つの単語を使用し、最初の単語は含まれる値の型を記述し、2 番目の単語は (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パッケージを使用する以外)。

リストに格納している構造体へのポインターが必要な場合、構造体の値を直接格納するのではなく、リスト内の構造体へのポインターを格納することが 1 つのオプションになります。*list.Elementまたは、含まれている構造への参照として値を渡すこともできます。

于 2013-03-22T05:20:20.493 に答える
2

インターフェイス値へのポインタを取得しますか?

インターフェイスタイプの変数が与えられた場合、変数に格納されている値へのポインタを取得する方法はありますか?

それは不可能。

ロブパイク

インターフェイス値は必ずしもアドレス可能ではありません。例えば、

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は、タイプ*Tのxへのポインターを生成します。オペランドはアドレス可能である必要があります。つまり、変数、ポインター間接参照、またはスライス索引付け操作のいずれかです。または、アドレス指定可能な構造体オペランドのフィールドセレクター。または、アドレス指定可能な配列の配列索引付け操作。アドレス指定可能性の要件の例外として、xは複合リテラルの場合もあります。

参照:

インターフェイスタイプ

タイプアサーション

Goデータ構造:インターフェース

Goインターフェース

于 2013-03-20T14:49:49.613 に答える
2

最初の概算では、それはできません。できたとしても、pそれ自体が型を持つ必要がinterface{}あり、あまり役に立ちません。その場合、直接逆参照することはできません。

必須の質問は次のとおりです。どのような問題を解決しようとしていますか?

最後になりましたが、インターフェイスは構造ではなく動作を定義します。一般に、インターフェイスの基になる実装型を直接使用すると、インターフェイスの契約が破られますが、一般的な正当なケースではない可能性があります。しかし、静的に既知の型の有限セットについては、型スイッチ ステートメントによって、これらは既に提供されています。

于 2013-03-20T08:59:44.133 に答える
2

型アサーションは、結果が 2 つの値になる式です。この場合、アドレスを取得するとあいまいになります。

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

コメントから:

これは、値自体へのポインターではなく、値のコピーへのポインターであることに注意してください。

ジェームズ・ヘンストリッジ

したがって、この問題の解決策は簡単です。値ではなく、ポインタをインターフェイスに格納します。

于 2013-03-20T09:51:25.357 に答える