Menu
Coddy logo textTech

Exportierte vs. nicht exportierte Felder

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

In Go wird die Kapselung auf Strukturebene durch die Groß- und Kleinschreibung der Feldnamen gesteuert. Diese einfache Regel bestimmt, ob auf Felder von außerhalb des Pakets zugegriffen werden kann, in dem die Struktur definiert ist.

Felder, die mit einem Großbuchstaben beginnen, sind exportiert: aus jedem Paket zugänglich. Felder, die mit einem Kleinbuchstaben beginnen, sind nicht exportiert: nur innerhalb desselben Pakets zugänglich:

// Im Paket "user"
type User struct {
    Name     string  // Exportiert - überall zugänglich
    Email    string  // Exportiert - überall zugänglich
    password string  // Unexportiert - nur im Paket "user" zugänglich
    age      int     // Unexportiert - nur im Paket "user" zugänglich
}

Wenn ein anderes Paket diese Struktur importiert und verwendet, kann es nur mit exportierten Feldern interagieren:

// Im Paket "main"
import "user"

func main() {
    u := user.User{
        Name:  "Alice",      // funktioniert
        Email: "a@mail.com", // funktioniert
        // password: "secret", // Kompilierfehler: unbekanntes Feld
    }
    
    fmt.Println(u.Name)     // funktioniert
    // fmt.Println(u.password) // Kompilierfehler: kann nicht auf unexportiertes Feld verweisen
}

Dieser Mechanismus schützt sensible Daten und interne Implementierungsdetails. Das Feld password kann von außerhalb des Pakets nicht direkt gelesen oder geändert werden, sodass anderer Code gezwungen ist, die von dir bereitgestellten Methoden zu verwenden. Dies ist Gos Ansatz zur Erreichung von Datenverbergung: ein grundlegendes Prinzip der Kapselung in der objektorientierten Programmierung.

challenge icon

Aufgabe

Einfach

Erstellen wir ein Bankkontosystem, das die Kapselung durch exportierte und nicht exportierte Felder demonstriert. Du erstellst ein Paket, das sensible Finanzdaten schützt und gleichzeitig sichere öffentliche Informationen bereitstellt.

Du organisierst deinen Code über zwei Dateien:

  • account.go: Erstelle eine BankAccount-Struktur im main-Paket, die ein echtes Bankkonto mit angemessenem Datenschutz modelliert:
    • HolderName (exportiert) – der Name des Kontoinhabers, der öffentlich angezeigt werden kann
    • AccountType (exportiert) – die Art des Kontos (z. B. „Savings“, „Checking“)
    • balance (nicht exportiert) – der tatsächliche Kontostand, der geschützt werden sollte
    • pin (nicht exportiert) – die PIN des Kontos, hochsensible Daten
    Füge eine Konstruktorfunktion NewBankAccount hinzu, die den Namen des Kontoinhabers, die Kontoart, den Anfangssaldo und die PIN entgegennimmt und anschließend einen Zeiger auf eine neue BankAccount zurückgibt. Füge außerdem eine Methode GetPublicInfo() string hinzu, die das folgende Format zurückgibt: Account: [HolderName] ([AccountType])
  • main.go: Lies die Kontodaten aus der Eingabe ein, erstelle mithilfe des Konstruktors ein BankAccount und demonstriere die Kapselung. Gib die öffentlichen Informationen mithilfe der Methode aus und greife anschließend direkt auf jedes exportierte Feld zu, wobei du sie in separaten Zeilen ausgibst. Die nicht exportierten Felder (balance und pin) sind geschützt. Du kannst sie nur über den Konstruktor festlegen.

Die folgenden Eingaben werden bereitgestellt:

  • Zeile 1: Name des Kontoinhabers
  • Zeile 2: Kontoart
  • Zeile 3: Anfangssaldo (als Gleitkommazahl)
  • Zeile 4: PIN-Code

Wenn beispielsweise Alice Johnson, Savings, 5000.50 und 1234 angegeben werden, sollte deine Ausgabe folgendermaßen aussehen:

Account: Alice Johnson (Savings)
Holder: Alice Johnson
Type: Savings

Beachte, dass der Kontostand und die PIN niemals in der Ausgabe erscheinen: Sie sind sicher innerhalb der Struktur verborgen und nur innerhalb des Pakets zugänglich. Das ist Kapselung in der Praxis: Sensible Daten werden geschützt, während öffentliche Informationen weiterhin zugänglich bleiben.

Probier es selbst

package main

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

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

	// Kontoinhaber-Namen lesen
	holderName, _ := reader.ReadString('\n')
	holderName = strings.TrimSpace(holderName)

	// Kontotyp lesen
	accountType, _ := reader.ReadString('\n')
	accountType = strings.TrimSpace(accountType)

	// Anfangssaldo lesen
	balanceStr, _ := reader.ReadString('\n')
	balanceStr = strings.TrimSpace(balanceStr)
	balance, _ := strconv.ParseFloat(balanceStr, 64)

	// PIN lesen
	pinStr, _ := reader.ReadString('\n')
	pin := strings.TrimSpace(pinStr)

	// TODO: Erstelle ein neues BankAccount mit dem Konstruktor
	// account := NewBankAccount(...)

	// TODO: Gib die öffentlichen Infos mit der GetPublicInfo()-Methode aus

	// TODO: Gib den Inhabernamen aus, indem du direkt auf das exportierte Feld zugreifst
	// fmt.Println("Holder:", ...)

	// TODO: Gib den Kontotyp aus, indem du direkt auf das exportierte Feld zugreifst
	// fmt.Println("Type:", ...)

	// Note: balance und pin sind unexportiert – auf sie kann hier nicht direkt zugegriffen werden
	// Sie sind sicher innerhalb der struct gekapselt

	_ = balance // Entferne diese Zeile, wenn du balance verwendest
	_ = pin     // Entferne diese Zeile, wenn du pin verwendest
}
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

Übe selbstständig: Online-Go-Compiler