Wenn die Drucklogik auf der Schnittstelle hängt aber nicht auf dem structs selbst, dann ist es besser, den Druck auf eine freie Funktion zu bewegen, die über eine Schnittstelle arbeitet.
In Ihrem Fall wird die Methode PrintStr
verwendet, um eine Zeichenfolge zu drucken, die ein Mitglied jeder Struktur ist.
In diesem Fall bedeutet dies, dass jede Struktur eine Schnittstelle implementieren muss, die die zum Drucken benötigte Zeichenfolge zurückgibt, und PrintStr
wird zu einer Funktion, die einen Printable
Parameter verwendet.
type First struct {
str string
}
type Second struct {
str string
}
type Printable interface {
String() string
}
func (p First) String() string {
return p.str
}
func (p Second) String() string {
return p.str
}
func PrintStr(p Printable) {
fmt.Print(p.String())
}
Ihre Nutzung des A
Schnittstelle ist nicht-idiomatische weil eine Schnittstelle nicht auf der Implementierung seine Funktionalität abhängen.
Stattdessen mit dieser Lösung können Sie immer noch die A-Schnittstelle halten, sondern vereinfachen jede Implementierung:
func (f First) PrintStr() {
PrintStr(f)
}
func (s Second) PrintStr() {
PrintStr(s)
}
Es ist noch redundant, aber die Logik liegt in der Funktion, die von dort aus aufgerufen wird, die Begrenzung muss im Fall einer Änderung der Drucklogik kopiert werden.
Dieses Muster ist in der Go-Standardbibliothek üblich, da viele nützliche Funktionen auf Schnittstellen basieren, die sie nicht erweitern können, z. B. io.Reader.
Es ist eine einfache Schnittstelle mit nur einer Methode, aber es wird gründlich von vielen anderen Paketen verwendet.
Wenn Sie die ioutil.ReadAll Funktion betrachten, könnte es argumentiert werden, dass es hätte als eine andere Methode der io.Reader
Schnittstelle implementiert werden können, aber dies hält Leser einfacher, konzentriert sich auf ihre einzige Methode, während jeder Implementierer ReadAll kostenlos nutzen kann.
Es scheint auch ein wenig redundant, 2 Strukturen mit den gleichen Typen zu haben. – TheHippo
Ja, aber das ist ein Spielzeugbeispiel. First und Second könnten einige Felder teilen und nicht andere. Der Punkt ist, dass ich möchte, dass sich eine Funktion auf genau dieselbe Weise für zwei verschiedene Typen verhält, ohne Code wiederholt zu haben. – Ekaterina