Getter- & Setter-Methoden
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 49 von 107.
Da auf nicht exportierte Felder nicht direkt von außerhalb eines Pakets zugegriffen werden kann, müssen Sie Methoden bereitstellen, die einen kontrollierten Zugriff ermöglichen. Diese werden üblicherweise Getter und Setter genannt.
In Go ist die Konvention für Getter einfach: Verwenden Sie den Feldnamen mit einem Großbuchstaben am Anfang. Verwenden Sie kein Präfix „Get“ – nutzen Sie einfach Balance(), nicht GetBalance():
type BankAccount struct {
balance int // nicht exportiert
}
// Getter - gibt den Wert zurück
func (b *BankAccount) Balance() int {
return b.balance
}
// Setter - ändert den Wert mit Validierung
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}
Die wahre Stärke von Settern liegt im Hinzufügen von Validierung oder Geschäftslogik. Anstatt externem Code zu erlauben, jeden beliebigen Wert direkt zu setzen, kontrollieren Sie, was zulässig ist:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}
Diese Deposit-Methode fungiert als spezialisierter Setter, der Regeln erzwingt – negative Einzahlungen sind nicht erlaubt. Externer Code muss über Ihre Methoden zugreifen, was sicherstellt, dass das Struct immer in einem gültigen Zustand bleibt. Das ist Kapselung in der Praxis: Die Daten werden verborgen, während kontrolliertes Verhalten offengelegt wird.
Aufgabe
EinfachLassen Sie uns einen Temperaturkonverter bauen, der eine ordnungsgemäße Kapselung mithilfe von Getter- und Setter-Methoden demonstriert. Sie erstellen ein Struct, das die Temperatur intern in Celsius speichert, aber einen kontrollierten Zugriff über Methoden mit Validierung ermöglicht.
Sie organisieren Ihren Code in zwei Dateien:
temperature.go: Erstellen Sie einTemperatureStruct mit einem nicht exportiertencelsiusFeld (float64). Implementieren Sie die folgenden Methoden:Celsius()- ein Getter, der die aktuelle Temperatur in Celsius zurückgibtSetCelsius(value float64)- ein Setter, der nur Werte bei oder über dem absoluten Nullpunkt (-273.15) akzeptiert. Wenn der Wert unter diesem Schwellenwert liegt, sollte die Temperatur unverändert bleiben.Fahrenheit()- gibt die in Fahrenheit umgerechnete Temperatur mit der Formel(celsius * 9/5) + 32zurückSetFahrenheit(value float64)- konvertiert die Eingabe von Fahrenheit in Celsius und speichert sie, aber nur, wenn der resultierende Celsius-Wert bei oder über -273.15 liegt
NewTemperature(celsius float64) *Temperaturehinzu, der eine auf den angegebenen Wert initialisierte Temperatur erstellt (gehen Sie von einer gültigen Eingabe für den Konstruktor aus).main.go: Lesen Sie Temperaturwerte aus der Eingabe ein und demonstrieren Sie die Getter/Setter-Methoden. Erstellen Sie eine Temperatur, zeigen Sie deren Werte in beiden Einheiten an, versuchen Sie dann, neue Werte zu setzen, und zeigen Sie die Ergebnisse.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Initialer Celsius-Wert
- Zeile 2: Neuer zu setzender Celsius-Wert
- Zeile 3: Neuer zu setzender Fahrenheit-Wert
Formatieren Sie alle Temperaturausgaben mit zwei Dezimalstellen. Geben Sie die folgende Sequenz aus:
- Nach der Erstellung:
C: [celsius] F: [fahrenheit] - Nach dem Setzen von Celsius:
C: [celsius] F: [fahrenheit] - Nach dem Setzen von Fahrenheit:
C: [celsius] F: [fahrenheit]
Zum Beispiel, gegeben 25, -300 und 212, sollte Ihre Ausgabe wie folgt aussehen:
C: 25.00 F: 77.00
C: 25.00 F: 77.00
C: 100.00 F: 212.00Beachten Sie, dass die zweite Zeile unveränderte Werte zeigt, da -300 unter dem absoluten Nullpunkt liegt und der Setter dies abgelehnt hat. Die dritte Zeile zeigt die Temperatur nach dem erfolgreichen Setzen von 212°F (was 100°C entspricht). Dies ist die Stärke von Settern – sie setzen Regeln durch, die Ihre Daten valide halten.
Spickzettel
Nicht exportierte Felder erfordern Getter- und Setter-Methoden für den kontrollierten Zugriff von außerhalb des Pakets.
Getter-Konvention
In Go verwenden Getter den Feldnamen mit einem großgeschriebenen Anfangsbuchstaben. Verwenden Sie kein Präfix "Get":
type BankAccount struct {
balance int // nicht exportiert
}
// Getter - gibt den Wert zurück
func (b *BankAccount) Balance() int {
return b.balance
}Setter mit Validierung
Setter ändern Werte und können Validierungen oder Geschäftslogik enthalten:
// Setter - ändert den Wert mit Validierung
func (b *BankAccount) SetBalance(amount int) {
if amount >= 0 {
b.balance = amount
}
}Spezialisierte Setter
Erstellen Sie Methoden, die spezifische Regeln erzwingen, anstatt eine direkte Wertzuweisung zu ermöglichen:
func (b *BankAccount) Deposit(amount int) bool {
if amount <= 0 {
return false
}
b.balance += amount
return true
}Dieser Ansatz gewährleistet die Kapselung: Daten werden verborgen, während kontrolliertes Verhalten offengelegt wird, wodurch Structs in einem gültigen Zustand bleiben.
Probier es selbst
package main
import (
"fmt"
)
func main() {
// Eingabewerte lesen
var initialCelsius float64
var newCelsius float64
var newFahrenheit float64
fmt.Scanln(&initialCelsius)
fmt.Scanln(&newCelsius)
fmt.Scanln(&newFahrenheit)
// TODO: Erstelle eine neue Temperature mit dem Konstruktor
// TODO: Gib die Anfangswerte im Format "C: [celsius] F: [fahrenheit]" mit 2 Dezimalstellen aus
// TODO: Versuche, einen neuen Celsius-Wert zu setzen und gib das Ergebnis aus
// TODO: Versuche, einen neuen Fahrenheit-Wert zu setzen und gib das Ergebnis aus
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool