it-swarm.com.de

So legen Sie Standardwerte in Go-Strukturen fest

Auf die folgende Frage gibt es mehrere Antworten/Techniken:

  1. Wie setze ich Standardwerte für Golang-Strukturen?
  2. Wie man Strukturen in Golang initialisiert

Ich habe ein paar Antworten, aber weitere Diskussionen sind erforderlich.

103
Prateek
  1. Erzwingen Sie eine Methode, um die Struktur abzurufen (die Konstruktormethode).

    Ein gutes Design besteht darin, Ihren Typ nicht zu exportieren, sondern 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 einfach dadurch geschehen, dass der Typ selbst nicht exportiert wird. Sie können die Funktion NewSomething und sogar die Felder Text und DefaultText exportieren, den Strukturtyp jedoch nicht

  2. Eine andere Möglichkeit, es für Ihr eigenes Modul anzupassen, ist die Verwendung von Config struct, um Standardwerte festzulegen (Option 5 im Link). Dies ist jedoch keine gute Möglichkeit.

47
Prateek

Eine mögliche Idee ist, 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
}
72
vodolaz095

Ein Problem mit Option 1 in der Antwort von Victor Zamanian ist, dass wenn der Typ nicht exportiert wird, Benutzer Ihres Pakets ihn nicht als Typ für Funktionsparameter usw. deklarieren können struct zB.

package candidate
// Exporting interface instead of struct
type Candidate interface {}
// Struct is not exported
type candidate struct {
    Name string
    Votes unit32 // 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 Candidate-Schnittstelle deklarieren. Der einzige Nachteil, den ich bei dieser Lösung feststellen kann, ist, dass alle unsere Methoden in der Schnittstellendefinition deklariert werden müssen, aber Sie könnten argumentieren, dass dies trotzdem eine gute Praxis ist.

20
wolfson109

Es gibt eine Möglichkeit, dies mit Tags zu tun, die mehrere Standardeinstellungen zulässt.

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 können die Standardeinstellungen festgelegt werden.

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 komplettes Programm auf einem Spielplatz .

Wenn Sie an einem komplexeren Beispiel interessiert sind, beispielsweise mit Slices und Maps, dann schauen Sie sich creasty/defaultse an

3
Mike Chirico

Von https://golang.org/doc/effective_go.html#composite_literals :

Manchmal ist der Nullwert nicht gut genug und ein Initialisierungskonstruktor ist erforderlich, wie in diesem Beispiel aus dem Paket os.

    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
}
2
RdB
type Config struct {
    AWSRegion                               string `default:"us-west-2"`
}
1
user10209901