Menu
Coddy logo textTech

Leeres Interface (any)

Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 28 von 107.

Das leere Interface ist ein Interface mit null Methoden. Da jeder Typ in Go mindestens null Methoden hat, erfüllt jeder Typ automatisch das leere Interface. Dadurch ist es in der Lage, Werte eines beliebigen Typs aufzunehmen.

var anything interface{}

anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}

Seit Go 1.18 wurde das Schlüsselwort any als Alias für interface{} eingeführt. Sie sind vollständig austauschbar, aber any ist sauberer zu lesen.

var value any = "Go is awesome"

Das leere Interface ist nützlich, wenn Sie Werte unbekannter oder variierender Typen verarbeiten müssen. Funktionen wie fmt.Println verwenden es, um Argumente jeglichen Typs zu akzeptieren:

func PrintAnything(v any) {
    fmt.Println("Value:", v)
}

func main() {
    PrintAnything(100)
    PrintAnything("text")
    PrintAnything(3.14)
}

Es gibt jedoch einen Nachteil. Wenn ein Wert in einem leeren Interface gespeichert wird, verlieren Sie den Zugriff auf seine spezifischen Typinformationen.

Sie können Methoden nicht direkt aufrufen oder auf Felder zugreifen, ohne vorher den zugrunde liegenden Typ zu extrahieren. Die nächsten Lektionen werden behandeln, wie Sie den konkreten Typ mithilfe von Type Assertions und Type Switches aus einem leeren Interface abrufen.

challenge icon

Aufgabe

Einfach

Lass uns einen flexiblen Speichercontainer bauen, der Werte jeden Typs mithilfe des leeren Interfaces aufnehmen kann. Du wirst eine einfache Box erstellen, die demonstriert, wie any es dir ermöglicht, verschiedene Typen in derselben Struktur zu speichern.

Du wirst deinen Code in zwei Dateien organisieren:

  • box.go: Definiere ein Box-Struct mit einem einzigen Feld Content vom Typ any. Erstelle eine NewBox-Konstruktorfunktion, die einen Wert beliebigen Typs akzeptiert und einen Zeiger auf eine Box zurückgibt, die diesen Wert enthält. Füge eine Describe-Methode hinzu, die einen String zurückgibt, der zeigt, was in der Box gespeichert ist.
  • main.go: Lies verschiedene Werte aus der Eingabe, erstelle Boxen, die einen Integer, einen String und einen Boolean enthalten, und gib dann die Beschreibung jeder Box aus, um zu zeigen, wie derselbe Box-Typ völlig unterschiedliche Werte aufnehmen kann.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Ein Integer-Wert
  • Zeile 2: Ein String-Wert
  • Zeile 3: Ein Boolean-Wert (true oder false)

Deine Describe-Methode sollte einen String in diesem Format zurückgeben:

Box contains: [value]

Zum Beispiel sollte bei 42, hello und true deine Ausgabe so aussehen:

Box contains: 42
Box contains: hello
Box contains: true

Die wichtigste Erkenntnis hierbei ist, dass dein einzelnes Box-Struct einen Integer, einen String oder einen Boolean speichern kann – alles nur, weil der Typ any Werte jeden Typs akzeptiert. Jede Box enthält etwas anderes, und doch sind sie alle vom selben Box-Typ.

Spickzettel

Das leere Interface (interface{}) ist ein Interface mit null Methoden. Da jeder Typ in Go mindestens null Methoden hat, erfüllt jeder Typ automatisch das leere Interface, wodurch es in der Lage ist, Werte eines beliebigen Typs zu speichern.

var anything interface{}

anything = 42
anything = "hello"
anything = true
anything = []int{1, 2, 3}

Ab Go 1.18 wurde das Schlüsselwort any als Alias für interface{} eingeführt. Sie sind vollständig austauschbar, aber any ist sauberer zu lesen:

var value any = "Go is awesome"

Das leere Interface ist nützlich für den Umgang mit Werten unbekannter oder variierender Typen. Funktionen können Argumente eines beliebigen Typs akzeptieren:

func PrintAnything(v any) {
    fmt.Println("Value:", v)
}

func main() {
    PrintAnything(100)
    PrintAnything("text")
    PrintAnything(3.14)
}

Kompromiss: Wenn ein Wert in einem leeren Interface gespeichert wird, geht der Zugriff auf seine spezifischen Typinformationen verloren. Man kann Methoden nicht direkt aufrufen oder auf Felder zugreifen, ohne vorher den zugrunde liegenden Typ mittels Type Assertions oder Type Switches zu extrahieren.

Probier es selbst

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)

func main() {
	reader := bufio.NewReader(os.Stdin)

	// Ganzzahlwert lesen
	line1, _ := reader.ReadString('\n')
	intVal, _ := strconv.Atoi(strings.TrimSpace(line1))

	// String-Wert lesen
	line2, _ := reader.ReadString('\n')
	strVal := strings.TrimSpace(line2)

	// Boolean-Wert lesen
	line3, _ := reader.ReadString('\n')
	boolVal, _ := strconv.ParseBool(strings.TrimSpace(line3))

	// TODO: Erstelle Boxen für jeden Wert mit NewBox
	// TODO: Gib die Beschreibung jeder Box mit der Describe-Methode aus

	// Verwende die Variablen, um Kompilierungsfehler zu vermeiden (entferne diese Zeilen bei der Implementierung)
	_ = intVal
	_ = strVal
	_ = boolVal

	// Beispielhaftes Ausgabeformat:
	// fmt.Println(box.Describe())
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung