Es gibt mehrere Antworten / Techniken auf die folgende Frage:
- Wie setze ich Standardwerte für Golang-Strukturen?
- So initialisieren Sie Strukturen in Golang
Ich habe ein paar Antworten, aber weitere Diskussionen sind erforderlich.
Es gibt mehrere Antworten / Techniken auf die folgende Frage:
Ich habe ein paar Antworten, aber weitere Diskussionen sind erforderlich.
Antworten:
Eine mögliche Idee besteht darin, eine separate Konstruktorfunktion zu schreiben
//Something is the structure we work with
type Something struct {
Text string
DefaultText string
}
// NewSomething create new instance of Something
func NewSomething(text string) Something {
something := Something{}
something.Text = text
something.DefaultText = "default text"
return something
}
NewSomething
und sogar die Felder Text
und DefaultText
exportieren, aber den Strukturtyp nicht exportieren something
.
reflect.New()
z. B. über), kann nicht erwartet werden, dass er über Ihre speziell benannte Factory-Funktion Bescheid weiß. In diesem Fall und ohne die Sprache selbst zu ändern, würde meiner Meinung nach nur eine Schnittstelle (nach der die Bibliothek suchen könnte) ausreichen.
Erzwingen Sie eine Methode, um die Struktur abzurufen (den Konstruktorweg).
Ein gutes Design besteht darin, Ihren Typ nicht zu exportieren, aber eine exportierte Konstruktorfunktion wie NewMyType () bereitzustellen, mit der Sie Ihre Struktur / Ihren Typ ordnungsgemäß initialisieren können. Geben Sie auch einen Schnittstellentyp und keinen konkreten Typ zurück, und die Schnittstelle sollte alles enthalten, was andere mit Ihrem Wert tun möchten. Und Ihr konkreter Typ muss diese Schnittstelle natürlich implementieren.
Dies kann erreicht werden, indem der Typ selbst einfach nicht exportiert wird. Sie können die Funktion NewSomething und sogar die Felder Text und DefaultText exportieren, aber den Strukturtyp nicht exportieren
Eine andere Möglichkeit, es für Ihr eigenes Modul anzupassen, ist die Verwendung einer Konfigurationsstruktur zum Festlegen von Standardwerten (Option 5 im Link). Dies ist jedoch keine gute Möglichkeit.
Ein Problem mit Option 1 als Antwort von Victor Zamanian ist, dass Benutzer Ihres Pakets, wenn der Typ nicht exportiert wird, ihn nicht als Typ für Funktionsparameter usw. deklarieren können. Eine Möglichkeit, dies zu umgehen, besteht darin, eine Schnittstelle anstelle der zu exportieren Struktur zB
package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
Name string
Votes uint32 // Defaults to 0
}
// We are forced to call the constructor to get an instance of candidate
func New(name string) Candidate {
return candidate{name, 0} // enforce the default value here
}
Damit können wir Funktionsparametertypen über die exportierte Kandidatenschnittstelle deklarieren. Der einzige Nachteil, den ich aus dieser Lösung ersehen kann, ist, dass alle unsere Methoden in der Schnittstellendefinition deklariert werden müssen, aber Sie könnten argumentieren, dass dies sowieso eine gute Praxis ist.
Votes unit32
sollte wahrscheinlich seinVotes uint32
Es gibt eine Möglichkeit, dies mit Tags zu tun, die mehrere Standardeinstellungen zulassen.
Angenommen, Sie haben die folgende Struktur mit 2 Standard-Tags default0 und default1 .
type A struct {
I int `default0:"3" default1:"42"`
S string `default0:"Some String..." default1:"Some Other String..."`
}
Jetzt ist es möglich, die Standardeinstellungen festzulegen.
func main() {
ptr := &A{}
Set(ptr, "default0")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=3 ptr.S=Some String...
Set(ptr, "default1")
fmt.Printf("ptr.I=%d ptr.S=%s\n", ptr.I, ptr.S)
// ptr.I=42 ptr.S=Some Other String...
}
Hier ist das komplette Programm auf einem Spielplatz .
Wenn Sie an einem komplexeren Beispiel interessiert sind, z. B. mit Slices und Maps, dann werfen Sie einen Blick auf creasty / defaultse
Von https://golang.org/doc/effective_go.html#composite_literals :
Manchmal ist der Nullwert nicht gut genug und ein initialisierender Konstruktor ist erforderlich, wie in diesem Beispiel aus dem Paket os abgeleitet.
func NewFile(fd int, name string) *File {
if fd < 0 {
return nil
}
f := new(File)
f.fd = fd
f.name = name
f.dirinfo = nil
f.nepipe = 0
return f
}
type Config struct {
AWSRegion string `default:"us-west-2"`
}