2016-11-09 2 views
0

Der folgende Code "eingebetteten Typ nicht ein Zeiger auf eine Schnittstelle sein kann," gibt Fehler bei der Kompilierung:Go Fehler:

type IFile interface { 
    Read() (n int, err error) 
    Write() (n int, err error) 
} 

type TestFile struct { 
    *IFile 
} 

Fehler:

./test.go:18: embedded type cannot be a pointer to interface

Warum kann ich nicht *IFile einbetten?

+0

Weil es verboten ist. – Volker

Antwort

1

Die Sprachspezifikation erlaubt dies nicht. Entsprechender Abschnitt aus der spec: Struct types:

A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct. An embedded type must be specified as a type name T or as a pointer to a non-interface type name *T , and T itself may not be a pointer type. The unqualified type name acts as the field name.

Ein Zeiger auf einen Schnittstelle Typ ist sehr selten sinnvoll, da eine Schnittstellentyp einen Zeiger oder einen Nicht-Zeiger-Wert halten kann.

gesagt haben, dass, wenn ein konkreter, die Ihren IFile Typ implementiert ein Zeigertyp ist, dann wird ein Zeigerwert in einem Schnittstellenwert IFile Typ gewickelt werden, so dass Sie immer noch IFile einbetten müssen, nur den Wert, der Arbeitsgeräte IFile wird ein Zeigerwert sein, z

// Let's say *FileImpl implements IFile: 
f := TestFile{IFile: &FileImpl{}} 

Edit: Antwort auf Ihren Kommentar:

Erstens ist dies Go, nicht C++. In Go sind Schnittstellen keine Zeiger, aber sie werden als ein Paar (type;value) dargestellt, wobei "Wert" ein Zeiger oder ein Nicht-Zeiger sein kann. Mehr dazu im Blogbeitrag: The Laws of Reflection: The representation of an interface.

Zweitens, wenn FileImpl ein Typ ist, f := TestFile{IFile : &FileIml} offensichtlich ein Fehler bei der Kompilierung ist, müssen Sie einen Wert von *FileImpl und &FileImpl ist eindeutig nicht. Du brauchst zum Beispiel eine composite literal welche in Form von &FileImpl{} ist, also sollte es so sein wie ich oben gepostet habe.

+0

Typ IFile Schnittstelle { Read() (n int, err-Fehler) Write() (n int, err-Fehler) } Typ FileImp { Zeichenfolge datei_name ..... } Typ struct Testfile { IFile } f: = {Testfile IFile: FileIml} ist f enthält Speicherkopie des FileImp Feld? –

+0

@sotter Das 'f.IFile'-Feld ist ein Interface-Typ, es enthält die Kopie von' FileImpl', also ja, 'f' enthält eine Kopie von' FileImpl'. Wenn Sie das nicht wollen, verwenden Sie einen Poitner, z.B. '& FileImpl', so wird nur eine Kopie des Zeigers gespeichert, aber es wird auf den gleichen 'FileImpl'-Wert zeigen. – icza

+0

danke, ich verstehe, dass jedoch 'f: = TestFile {IFile: & FileIml}' kann nicht erstellt werden. In C++ ist Interface ein Pointer, deshalb möchte ich TestFile struct {* IFile} 'in golang schreiben. –