Die Go-Sprache kann Typzusicherungen verwenden, um Schnittstellentypen auszuführen. Unabhängig davon, ob Sie in Go einen Schnittstellentyp in einen anderen Schnittstellentyp oder eine Schnittstelle in einen anderen Basistyp konvertieren, müssen Sie Typzusicherungen verwenden. Es gibt zwei Arten der Konvertierungssyntax: „Konvertierte Variablen: = Schnittstellenvariablen. (Zieltyp)“ und „Konvertierte Variable, ok := Schnittstellenvariable.(Zieltyp)“.
Die Betriebsumgebung dieses Tutorials: Windows 7-System, GO Version 1.18, Dell G3-Computer.
Um in Golang einen Schnittstellentyp in einen anderen Schnittstellentyp oder eine Schnittstelle in einen anderen Basistyp zu konvertieren, müssen Sie Typzusicherungen verwenden.
Format der Typzusicherung
Typzusicherung ist eine Operation, die für Schnittstellenwerte verwendet wird. Syntaktisch sieht es so aus, als ob i.(T) ein Assertionstyp genannt wird, wobei i einen Schnittstellentyp und T einen Typ darstellt. Eine Typzusicherung prüft, ob der dynamische Typ des Objekts, auf das sie angewendet wird, mit dem zugesicherten Typ übereinstimmt.
Das Grundformat der Typzusicherung ist wie folgt:
t := i.(T)
wobei i die Schnittstellenvariable, T den konvertierten Zieltyp und t die konvertierte Variable darstellt.
Hier gibt es zwei Möglichkeiten. Wenn der behauptete Typ T ein konkreter Typ ist, prüft die Typzusicherung zunächst, ob der dynamische Typ von i mit T identisch ist. Wenn diese Prüfung erfolgreich ist, ist das Ergebnis der Typzusicherung der dynamische Wert von i, der natürlich vom Typ T ist. Mit anderen Worten: Eine Typzusicherung für einen konkreten Typ erhält einen konkreten Wert von seinem Operanden. Wenn die Prüfung fehlschlägt, löst der nachfolgende Vorgang eine Panik aus. Zum Beispiel:
var w io.Writer w = os.Stdout f := w.(*os.File) // 成功: f == os.Stdout c := w.(*bytes.Buffer) // 死机:接口保存*os.file,而不是*bytes.buffer
Zweitens: Wenn der bestätigte Typ T stattdessen ein Schnittstellentyp ist, prüft die Typzusicherung, ob der dynamische Typ von i T erfüllt. Wenn diese Prüfung erfolgreich ist, wird der dynamische Wert nicht abgerufen; das Ergebnis ist immer noch ein Schnittstellenwert mit denselben Typ- und Wertteilen, aber das Ergebnis hat den Typ T. Mit anderen Worten: Eine Typzusicherung für einen Schnittstellentyp ändert die Art und Weise, wie der Typ dargestellt wird, und ändert den Satz verfügbarer Methoden (normalerweise größer), schützt jedoch die dynamischen Typ- und Wertteile des Schnittstellenwerts.
Nach der ersten Typzusicherung unten enthalten sowohl w als auch rw os.Stdout, sodass sie jeweils einen dynamischen Typ *os.File haben, aber die Variable w ist ein io.Writer-Typ, der nur die Write-Methode der Datei verfügbar macht, jedoch die rw Variable macht nur ihre Read-Methode verfügbar.
var w io.Writer w = os.Stdout rw := w.(io.ReadWriter) // 成功:*os.file具有读写功能 w = new(ByteCounter) rw = w.(io.ReadWriter) // 死机:*字节计数器没有读取方法
Wenn das Objekt der Assertionsoperation ein Null-Schnittstellenwert ist, schlägt die Typassertion fehl, unabhängig vom Typ, der behauptet wird. Es besteht fast keine Notwendigkeit, einen weniger restriktiven Schnittstellentyp (weniger Methodensatz) zu bestätigen, da er sich wie eine Zuweisungsoperation verhält, mit Ausnahme von Null-Schnittstellenwerten.
Wenn ich die Methode der T-Schnittstelle nicht vollständig umsetze, löst diese Anweisung einen Absturz aus. Das Auslösen von Ausfallzeiten ist nicht sehr benutzerfreundlich, daher gibt es eine andere Möglichkeit, die obige Aussage zu schreiben:
t,ok := i.(T)
Wenn die Schnittstelle nicht implementiert ist, wird auf diese Weise ok auf false und t auf einen 0-Wert vom Typ T gesetzt . In der normalen Implementierung ist ok wahr. Hier kann man sich ok vorstellen als: das Ergebnis, ob die Schnittstelle i den Typ T implementiert.
Schnittstellen in andere Schnittstellen konvertieren
Ein Typ, der eine bestimmte Schnittstelle implementiert, implementiert auch eine andere Schnittstelle. Zu diesem Zeitpunkt können Sie zwischen den beiden Schnittstellen konvertieren.
Vögel und Schweine haben unterschiedliche Eigenschaften. Vögel können fliegen, Schweine können nicht fliegen, aber beide Tiere können laufen. Wenn Sie Strukturen zur Implementierung von Vögeln und Schweinen verwenden, ermöglichen die Methoden Fly() und Walk(), die ihnen eigene Eigenschaften verleihen, den Vögeln und Schweinen die Implementierung der Schnittstelle für fliegende Tiere (Flyer) bzw. der Schnittstelle für laufende Tiere (Walker).
Nachdem die Instanzen von Vögeln und Schweinen erstellt wurden, werden sie in einer Karte vom Typ interface{} gespeichert. Der Typ interface{} stellt eine leere Schnittstelle dar, was bedeutet, dass diese Schnittstelle als beliebiger Typ gespeichert werden kann. Führen Sie eine Assertionsoperation für die Variable interface{} aus, die die Instanz von Bird oder Pig enthält. Wenn es sich bei dem Assertionsobjekt um den durch die Assertion angegebenen Typ handelt, wird eine in den Assertionsobjekttyp konvertierte Schnittstelle zurückgegeben , der zweite Parameter der Behauptung gibt false zurück.
Zum Beispiel der folgende Code:
var obj interface = new(bird) f, isFlyer := obj.(Flyer)
Im Code generiert new(bird) eine Bird-Instanz vom Typ *bird, und diese Instanz wird in der obj-Variablen vom Typ interface{} gespeichert. Verwenden Sie die Assertion vom Typ obj.(Flyer), um obj in die Flyer-Schnittstelle zu konvertieren. f ist der Flyer-Schnittstellentyp, wenn die Konvertierung erfolgreich ist, isFlyer gibt an, ob die Konvertierung erfolgreich ist, und der Typ ist bool.
Das Folgende ist der detaillierte Code (Code 1):
package main import "fmt" // 定义飞行动物接口 type Flyer interface { Fly() } // 定义行走动物接口 type Walker interface { Walk() } // 定义鸟类 type bird struct { } // 实现飞行动物接口 func (b *bird) Fly() { fmt.Println("bird: fly") } // 为鸟添加Walk()方法, 实现行走动物接口 func (b *bird) Walk() { fmt.Println("bird: walk") } // 定义猪 type pig struct { } // 为猪添加Walk()方法, 实现行走动物接口 func (p *pig) Walk() { fmt.Println("pig: walk") } func main() { // 创建动物的名字到实例的映射 animals := map[string]interface{}{ "bird": new(bird), "pig": new(pig), } // 遍历映射 for name, obj := range animals { // 判断对象是否为飞行动物 f, isFlyer := obj.(Flyer) // 判断对象是否为行走动物 w, isWalker := obj.(Walker) fmt.Printf("name: %s isFlyer: %v isWalker: %v\n", name, isFlyer, isWalker) // 如果是飞行动物则调用飞行动物接口 if isFlyer { f.Fly() } // 如果是行走动物则调用行走动物接口 if isWalker { w.Walk() } } }
Die Codebeschreibung lautet wie folgt:
Zeile 6 definiert die Schnittstelle des fliegenden Tieres.
Zeile 11 definiert die Schnittstelle für wandelnde Tiere.
Die Zeilen 16 und 30 definieren jeweils Vogel- und Schweineobjekte und implementieren die Schnittstellen für fliegende Tiere bzw. laufende Tiere.
Zeile 41 ist eine Karte, die Objektnamen und Objektinstanzen abbildet. Die Instanzen sind Vögel und Schweine.
Zeile 47 beginnt mit der Durchquerung der Karte, obj ist der Schnittstellentyp interface{}.
第 50 行中,使用类型断言获得 f,类型为 Flyer 及 isFlyer 的断言成功的判定。
第 52 行中,使用类型断言获得 w,类型为 Walker 及 isWalker 的断言成功的判定。
第 57 和 62 行,根据飞行动物和行走动物两者是否断言成功,调用其接口。
代码输出如下:
将接口转换为其他类型
在代码 1 中,可以实现将接口转换为普通的指针类型。例如将 Walker 接口转换为 *pig 类型,请参考下面的代码:
p1 := new(pig) var a Walker = p1 p2 := a.(*pig) fmt.Printf("p1=%p p2=%p", p1, p2)
对代码的说明如下:
第 3 行,由于 pig 实现了 Walker 接口,因此可以被隐式转换为 Walker 接口类型保存于 a 中。
第 4 行,由于 a 中保存的本来就是 *pig 本体,因此可以转换为 *pig 类型。
第 6 行,对比发现,p1 和 p2 指针是相同的。
如果尝试将上面这段代码中的 Walker 类型的 a 转换为 *bird 类型,将会发出运行时错误,请参考下面的代码:
p1 := new(pig) var a Walker = p1 p2 := a.(*bird)
运行时报错:
panic: interface conversion: main.Walker is *main.pig, not *main.bird
报错意思是:接口转换时,main.Walker 接口的内部保存的是 *main.pig,而不是 *main.bird。
因此,接口在转换为其他类型时,接口内保存的实例对应的类型指针,必须是要转换的对应的类型指针。
总结
接口和其他类型的转换可以在Go语言中自由进行,前提是已经完全实现。
接口断言类似于流程控制中的 if。但大量类型断言出现时,应使用更为高效的类型分支 switch 特性。
Das obige ist der detaillierte Inhalt vonSo konvertieren Sie den Go-Sprachschnittstellentyp. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!