Yaml: Standardwert

Erstellt am 21. März 2016  ·  13Kommentare  ·  Quelle: go-yaml/yaml

Hallo,

Ich wollte fragen, ob es möglich ist, die Nullwerte für int neu zu definieren. Ich brauche zum Beispiel so etwas:

...
  # int32
  max: 2147483647
  min: -2147483648

Wenn der Wert festgelegt ist, sollte er den angegebenen Wert verwenden, und wenn kein Wert angegeben ist, sollte er den definierten Null-/Standardwert verwenden. Leider kann ich 0 nicht als Nullwert verwenden, da es sich um einen gültigen Wert für Min/Max handelt.

Meine aktuelle Lösung besteht darin, ein string anstelle von int zu verwenden.

Hilfreichster Kommentar

Sie müssen UnmarshalYAML für Stuff implementieren:

func (s *Stuff) UnmarshalYAML(unmarshal func(interface{}) error) error {
    type rawStuff Stuff
    raw := rawStuff{} // Put your defaults here
    if err := unmarshal(&raw); err != nil {
        return err
    }

    *s = Stuff(raw)
    return nil
}

Alle 13 Kommentare

Sie können einfach Standardwerte festlegen, wenn Sie einen Wert ungleich Null angeben:

type Stuff struct {
  Max int32
  Min int32
}

func Parse(in []byte) error {
  var stuff = Stuff{Max: 2147483647, Min: -147483648}
  if err := yaml.Unmarshal(in, &stuff); err != nil {
    return err
  }
  ...
  return nil
}

Eine andere Option wäre die Verwendung von:

type Stuff struct {
  Max *int32
  Min *int32
}

Sie können dann erkennen, dass der Wert nicht eingestellt wurde, und ihn korrigieren.

Wird die erste Option tatsächlich unterstützt? Ich habe es getestet und der Wert der Eigenschaft wird auf den Standardwert seines Typs zurückgesetzt, wenn der Wert nicht in der Yaml-Datei angegeben ist.

Bearbeiten: Ich habe auch die Tests durchsucht und konnte keinen für diesen Fall finden.

@vincentbernat Tolle Tipps, ich habe mich über diese beiden Ansätze gewundert, und sie funktionieren großartig! Kleiner Tippfehler, ich glaube du brauchst ein = Zeichen:

  var stuff = Stuff{Max: 2147483647, Min: -147483648} # type is infered

Danke noch einmal!

Wie machen Sie das für komplexere Strukturen, bei denen die Unterstrukturen einen Standardwert haben sollten ... ZB:

type SomeStruct struct {
    A     string `yaml:"a"`
    Things struct {
        Foo []*Stuff `yaml:"foo"`
    } `yaml:"things"`
    Comment string `yaml:"comment"`
}

Und wenn ich möchte, dass die Elemente im Foo-Array Standardwerte haben ...

... Es sieht so aus, als müsste ich die Unmarshaler-Schnittstelle implementieren ... https://godoc.org/gopkg.in/yaml.v2#Unmarshaler und das per Struct tun ... Daran arbeiten ...

Sie müssen UnmarshalYAML für Stuff implementieren:

func (s *Stuff) UnmarshalYAML(unmarshal func(interface{}) error) error {
    type rawStuff Stuff
    raw := rawStuff{} // Put your defaults here
    if err := unmarshal(&raw); err != nil {
        return err
    }

    *s = Stuff(raw)
    return nil
}

@vincentbernat Cool...

Es scheint also Folgendes:

type rawStuff Stuff

ist im Grunde eine Umleitung zum "Schummeln" und als Ergebnis die unendliche Rekursion zu vermeiden, die ich sah, als ich den temporären "rohen" Typ nicht ersetzte ... Ist diese Analyse korrekt?

Ist das das idiomatische Muster für so etwas?

Danke noch einmal!

PS: Dies sind jetzt zwei Projekte, die ich verwende, wo ich Ihren Namen gesehen habe. Ich schätze, ich schulde dir an dieser Stelle einen Drink!

Ja, Ihre Analyse ist richtig. Ich kann nichts über den idiomatischen Teil sagen, da ich nur ein normaler Benutzer bin (und noch kein sehr erfahrener). Ich werde das Getränk jederzeit nehmen, aber ich werde es wahrscheinlich in zwei Wochen vergessen. :)

Netter Austausch. Abschließend scheinen die Fragen sortiert worden zu sein.

@niemeyer Ich würde sagen, dass dies einen Doc-Patch benötigt, bevor Sie schließen. Können Sie bitte wieder öffnen und den Titel ändern?

Wenn Sie eine klare Vorstellung davon haben, was dokumentiert werden soll, reichen Sie bitte einen Vorschlag ein.

Sie müssen UnmarshalYAML für Stuff implementieren:

func (s *Stuff) UnmarshalYAML(unmarshal func(interface{}) error) error {
    type rawStuff Stuff
    raw := rawStuff{} // Put your defaults here
    if err := unmarshal(&raw); err != nil {
        return err
    }

    *s = Stuff(raw)
    return nil
}

Netter und intelligenter Trick, aber ich werde nicht funktionieren, wenn Sie eine leere Zeichenfolge an den Unmarshaller übergeben:

func main() {
    unmarshalled := &speedProviderConfig{}
    yamlStr := ""
    err := yaml.Unmarshal([]byte(yamlStr), unmarshalled)
}

type speedProviderConfig struct {
    MinimumBytesPerSeconds int64 `yaml:"min"`
    MaximumBytesPerSeconds int64 `yaml:"max"`
}

func (c *speedProviderConfig) UnmarshalYAML(value *yaml.Node) error {
    type rawSpeedProviderConfig speedProviderConfig // create a subtype to trick goyaml. If we where using Decode() on a speedProviderConfig it will go into an infinite recursion
    conf := rawSpeedProviderConfig{
        MinimumBytesPerSeconds: 5000,
        MaximumBytesPerSeconds: 15000,
    }

    err := value.Decode(&conf)
    if err != nil {
        return errors.Wrapf(err, "bandwidth.speedProviderConfig: failed to unmarshall")
    }

    *c = speedProviderConfig(conf)

    return nil
}

Die obige main() -Funktion erzeugt einen speedProvider -Wert von 0 und 0. Wenn der String leer ist, scheint das Umnarshalling überhaupt nicht stattzufinden, und es bedeutet auch, dass unsere Standardwerte nicht vorhanden sind einstellen.

Was ich empfehle ist:

func main() {
    unmarshalled := defaultSpeedProviderConfig()
    yamlStr := ""
    err := yaml.Unmarshal([]byte(yamlStr), unmarshalled)
}

type speedProviderConfig struct {
    MinimumBytesPerSeconds int64 `yaml:"min"`
    MaximumBytesPerSeconds int64 `yaml:"max"`
}

func defaultSpeedProviderConfig() *speedProviderConfig {
    return &speedProviderConfig{
        MinimumBytesPerSeconds: 5000,
        MaximumBytesPerSeconds: 15000,
    }
}

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

mro picture mro  ·  13Kommentare

thallgren picture thallgren  ·  8Kommentare

zubairhamed picture zubairhamed  ·  8Kommentare

rogpeppe picture rogpeppe  ·  7Kommentare

rojer picture rojer  ·  4Kommentare