Dies begann als einfacher Beitrag zu einer internen Slack-Gruppe. Dann wurde ich gebeten, es auf einem anderen Kanal in diesem Slack zu posten. Dann habe ich beschlossen, es im DevRel Collective Slack zu veröffentlichen. Zu diesem Zeitpunkt wurde ich gebeten, einen Blog-Beitrag zu erstellen, damit er nicht im Scroll-Back verloren geht (DevRel Collective verwendet ein kostenloses Slack-Konto, sodass wir nur 10.000 Nachrichten zurückblättern können. Bei mehr als 2.000 Mitgliedern geschieht dies schneller als du denkst. Aber ich schweife ab.)

Warum diese Tools

Ich entwickleviel in Go. Ich hätte wirklich nie gedacht, dass ich es tun würde, aber wenn Sie dies oder dies gelesen haben Entwicklung-ist-eine-Sache) oder [dies] (/ posts / category / camunda / Briefe-an-Santan-Autmotaing-Freude-an-der-Welt-im Maßstab) Sie werden sehen, dass ich gelutscht wurde in. (Noch ein kurzer Exkurs. Ja, ich habe von Rust gehört. Es ist die nächste Sprache auf meiner Liste. Geben Sie mir eine Minute.)

Go ist zu meiner Lieblingssprache geworden, weil ich jetzt weiß, wie man schnell damit umgeht. Es ist auch einfach, plattformübergreifend zu arbeiten, damit ich auf meinem Mac entwickeln und unter Linux bereitstellen kann, und es funktioniert einfach.

Bei den meisten meiner Arbeiten mit Go beschäftige ich mich mit Daten in json und Konfigurationsdateien in yaml oder toml die meiste Zeit, daher ist es immer willkommen, Tools zu finden, die den Umgang mit diesen Daten erleichtern!

Am Ende gibt es ein Bonus-Tool, wenn Sie das Ganze lesen.

JSON Zuerst

Im Umgang mit JSON gibt es in Go drei allgemeine Dinge, die ich ständig tun muss:

  • Überprüfen Sie den JSON
  • Unmarshall eines JSON-Objekts in eine Go-Struktur
  • Greifen Sie auf ein bestimmtes Feld in einem JSON-Objekt zu

JSON validieren

Die Validierung des JSON ist nicht immer erforderlich, aber normalerweise eine gute Idee. Nichts ist frustrierender, als zu versuchen, mit einem JSON-Objekt umzugehen, nur um herauszufinden, dass das, womit Sie sich befassen wollen, nicht das richtige JSON ist.

Daher validiere ich den JSON zuerst mit jasonlint. Fügen Sie Ihr json-Objekt ein und Sie werden sofort darüber informiert, ob es sich bei dem, was Sie zur Hand haben, tatsächlich um ein gültiges JSON-Objekt handelt.

Unmarshall ein JSON-Objekt

Go bietet einige praktische Möglichkeiten, um mit JSON-Objekten umzugehen, die es zu meiner Anlaufstelle für JSON-Daten machen. Wenn Sie ein JSON-Objekt erhalten, z. B. wenn Sie eine Website über eine API nach Daten abfragen, können Sie diese verwenden


  err := json.Unmarshal(data, &myStruct)

Und die Daten werden nicht in Ihre Datenstruktur übernommen. Aber, und es ist ein großes Problem, Sie müssen eine Datenstruktur haben, die genau zu Ihren eingehenden Daten passt.

Und hier kommt json-to-go ins Spiel. Nehmen Sie Ihr validiertes JSON-Objekt, übergeben Sie es auf der linken Seite und rechts heraus Seite kommt eine gültige Go-Datenstruktur, um sie zu halten.


  {
    "name": "David",
    "ParentEmailAddress": "spam@davidgs.com",
    "letter": "I want a pony",
    "address": {
      "home": "Not your business where I live",
      "work": "Also probably none of your business, but Camunda"
    }
  }

Ich habe das durch den JSON-Linter laufen lassen, und es ist gültig. Groß. Nun eine Go-Struktur, um es zu halten:


  type Autogenerated struct {
    Name               string `json:"name"`
    Parentemailaddress string `json:"ParentEmailAddress"`
    Letter             string `json:"letter"`
    Address            struct {
      Home string `json:"home"`
      Work string `json:"work"`
    } `json:"address"`
  }

Und jetzt kann ich einen Go-Code schreiben:


  import (
    "encoding/json"
    "log"
  )
  myStruct = Autogenerated{}
  data := getJsonData()
  err := json.Unmarshal(data, &myStruct)
  if err != nil {
    log.Fatal(err)
  }

Und myStruct ist eine ordnungsgemäß ausgefüllte Datenstruktur mit den Daten meines eingehenden JSON-Objekts.

Damit komme ich zum dritten Schritt: Zugriff auf bestimmte Felder eines JSON-Objekts.

Greifen Sie auf ein bestimmtes Feld eines JSON-Objekts zu

Mit unserer einfachen JSON-Struktur oben wäre dies größtenteils kein schwieriges Problem. Willst du die Arbeitsadresse?


  work_address = jsonObject.address.work

und du bist da Was aber, wenn Ihr JSON-Objekt massiv kompliziert ist?


  {
    "status": "OK",
    "results": [
      {
        "geometry": {
          "location": {
            "lat": 37.4229181,
            "lng": -122.0854212
          },
          "viewport": {
            "northeast": {
              "lat": 37.4242670803,
              "lng": -122.08407222
            },
            "southwest": {
              "lat": 37.4215691197,
              "lng": -122.08677018
            }
          },
          "location_type": "ROOFTOP"
        },
        "address_components": [
          {
            "long_name": "1600",
            "short_name": "1600",
            "types": [
              "street_number"
            ]
          },
          {
            "long_name": "Amphitheatre Pkwy",
            "short_name": "Amphitheatre Pkwy",
            "types": [
              "route"
            ]
          },
          {
            "long_name": "Mountain View",
            "short_name": "Mountain View",
            "types": [
              "locality",
              "political"
            ]
          },
          {
            "long_name": "Santa Clara",
            "short_name": "Santa Clara",
            "types": [
              "administrative_area_level_2",
              "political"
            ]
          },
          {
            "long_name": "California",
            "short_name": "CA",
            "types": [
              "administrative_area_level_1",
              "political"
            ]
          },
          {
            "long_name": "United States",
            "short_name": "US",
            "types": [
              "country",
              "political"
            ]
          },
          {
            "long_name": "94043",
            "short_name": "94043",
            "types": [
              "postal_code"
            ]
          }
        ],
        "formatted_address": "1600 Amphitheatre Pkwy, Mountain View, CA 94043, USA",
        "types": [
          "street_address"
        ]
      }
    ]
}

Und das ist im Vergleich zu einigen, mit denen ich mich regelmäßig beschäftige, nicht einmal komplex, aber um der Argumentation willen sagen wir, es ist so. Angenommen, Sie möchten den zweiten Typ aus der Adresskomponente herausholen, die im obigen Beispiel die Stadt “Mountain View” ist. Nun, das “Ergebnis” ist eigentlich ein Array, obwohl es im obigen Beispiel nur ein Element enthält. Wenn das Array viele Elemente enthält und Sie das Ergebnis des dritten Elements im Array haben möchten, wird es etwas schwieriger.

Hier kommt json selector ins Spiel. Fügen Sie Ihr JSON-Objekt ein (von dem wir bereits wissen, dass es gültig ist, weil Sie es validiert haben,richtig?) Und klicken Sie dann einfach auf was Sie wollen.


['results'][0]['address_components'][2]['types'][1]

Oh Himmel! Da ist! Es ist das erste Element im Array “results”, das Feld “address_components” und das dritte Element in dem Array “that *” und das zweite Element des Arrays “types”!

Denken Sie daran, die Array-Nummerierung beginnt bei Null!

Ein komplettes Toolset

Und das ist ein komplettes Toolset für den Umgang mit JSON-Objekten. Aber warte, ich habe “yaml” erwähnt und noch nicht darüber gesprochen!

Richtig! Und danke fürs Aufpassen!

YAML

YAML: Noch eine Markup-Sprache. Denn was die Welt braucht, sind mehr Auszeichnungssprachen. Aber yaml ist super nützlich für Konfigurationsdateien. Ich benutze yaml-basierte Konfigurationsdateien für alle möglichen Dinge. Die Konfigurationsdatei zum Erstellen dieser gesamten Website ist eine Yaml-Datei.

Daher ist es wichtig, eine “Yaml” -Datei richtig analysieren und verarbeiten zu können.

Wiederum ist es mit Go relativ einfach. Mein erstes Tool ist yaml2go. Genau wie bei json-to-go wird Ihre yaml-Dateistruktur in Go-Datenstrukturen umgewandelt.


  # Paste your yaml here...
  kind: test
  metadata:
    name: cluster
    namespace: test-ns

And get yourself some spiffy Go code:

// MyYaml
type MyYaml struct {
  Kind     string   `yaml:"kind"`
  Metadata Metadata `yaml:"metadata"`
}

// Metadata
type Metadata struct {
  Name      string `yaml:"name"`
  Namespace string `yaml:"namespace"`
}

Und dann können Sie Ihre Konfigurationsdatei entfernen:


  import (
    "io/ioutil"
    "log"
    "gopkg.in/yaml.v2"
  )
  var config MyYaml
  // InitConfig reads the config file and sets up the config struct
  func InitConfig(){
    dat, err := ioutil.ReadFile("./config.yaml")
    if err != nil {
      log.Fatal("No startup file: ", err)
    }
    err = yaml.Unmarshal(dat, &config)
    if err != nil {
      log.Fatal(err)
    }
  }

Und kümmern Sie sich von dort aus um Ihre Konfigurationsvariablen. Wenn Sie fertig sind und Ihre Datei “config.yaml” ausschreiben möchten (Sie wissen, wenn Ihr laufendes Programm Startparameter geändert hat), können Sie alles nach dem Marshalling ausschreiben:


  import (
    "io/ioutil"
    "log"
    "gopkg.in/yaml.v2"
  )
  // WriteDictators outputs the entire config file
  func WriteConfig() {
    newConf, err := yaml.Marshal(config)
    if err != nil {
      log.Fatal(err)
    }
    err = ioutil.WriteFile("./config.yaml", newConf, 0644)
    if err != nil {
      panic(err)
    }
  }

Sie haben jetzt Ihre alte Konfigurationsdatei mit Ihrer neuen Konfigurationsdatei überschrieben. Es ist im Wesentlichen dasselbe wie JSON, nur für “yaml”.

Bonus Tool Zeit!

Dieser hat meinen Speck mehr als einmal gerettet. Weil ich wirklich ** wirklich * am Schreiben von regulären Ausdrücken (RegEx) scheiße bin. Wie wirklich. Ich bin schrecklich darin. So schrecklich darin, dass ich, bis ich dieses Werkzeug gefunden habe, 30 Zeilen Go-Code zu ungefähr einem einzelnen Aufruf einer Regex schreiben würde.

Nicht. Irgendein. Mehr!

Geben Sie [RegEx101] ein (https://regex101.com). Ich kann gar nicht sagen, wie brillant dieses Tool ist. Lassen Sie mich erklären.

Möglicherweise stellen Sie fest (oder auch nicht), dass diese Website in eine Reihe von Sprachen übersetzt wurde. Ich spreche keinen von ihnen. Ich schreibe keinen von ihnen. Aber ich schreibe Go. Mit den Übersetzungs-APIs von Go und Google kann ich jeden Beitrag hier automatisch in die gewünschte (n) Sprache (n) übersetzen.

Aber die Übersetzungs-API macht einige Dinge mit Teilen einer Markdown-Datei ernsthaft durcheinander. Also musste ich kompensieren. URLs sind ein gutes Beispiel. Wenn in meiner Datei “blog-post.md” ein Link “mein Link” enthalten ist, übersetzt Google Translate gerne “[mein Link]”, den ich möchte, und fügt dann einen hinzu Leerzeichen zwischen ] (, was ich nicht will, und dann (manchmal) die Pfadkomponenten des Links übersetzen, die ich definitiv nicht will.

Also musste ich wie gesagt entschädigen. Zuerst habe ich das manuell gemacht und es war ein echtes Durcheinander. Es war fehleranfällig und schwer zu warten. Aber dann habe ich RexEx101 gefunden und alles hat sich geändert.

Ich könnte das tun: Ein regulärer Ausdruck, der die URL im obigen Absatz findet

Und dann erklärt es sogar, was die Varoius-Teile des Regex tun!

Erklärung, welche Teile des regulären Ausdrucks übereinstimmen

Dann kann mein Go-Programm alle URLs in einem bestimmten Text finden und nach der Übersetzung des Textes alle “](original/url)” durch “] (original / url)” ersetzen


  // fix URLs because google translate changes [link](http://your.link) to
  // [link] (http://your.link) and it *also* will translate any path
  // components, thus breaking your URLs.
  reg := regexp.MustCompile(`]\([-a-zA-Z0-9@:%._\+~#=\/]{1,256}\)`)
  // get all the URLs with a single RegEx, keep them for later.
  var foundUrls [][]byte = reg.FindAll([]byte(xlate), -1)
  ...
  // translate the bit
  // Now it's time to go back and replace all the fucked up urls ...
  reg = regexp.MustCompile(`] \([-a-zA-Z0-9@:%._\+~#=\/ ]{1,256}\)`)
  for x := 0; x < len(foundUrls); x++ {
    tmp := reg.FindIndex([]byte(translated))
    if tmp == nil {
      break
    }
    t := []byte(translated)
    translated = fmt.Sprintf("%s(%s%s", string(t[0:tmp[0]+1]), string(foundUrls[x][2:]), (string(t[tmp[1]:])))
  }

Ich könnte es auch benutzen, um das andere Ende zu finden: Regex, um die durcheinandergebrachten URLs zu finden

Und es erklärt immer hilfreich, was es tut:

Erklärung, wie die Regex mit verschiedenen Teilen des Eingabetextes übereinstimmte

Oh mein! Ich könnte auch die anderen Dinge reparieren, die Google Trnaslate durcheinander bringt, wie fetter Text ** fett ** wird ** fett **, was nicht mehr fett ist. Aber damit:


// a bunch of regexs to fix other broken stuff
	reg = regexp.MustCompile(` (\*\*) ([A-za-z0-9]+) (\*\*)`) // fix bolds (**foo**)
	translated = string(reg.ReplaceAll([]byte(translated), []byte(" $1$2$3")))
	reg = regexp.MustCompile(`&quot;`) // fix escaped quotes
	translated = string(reg.ReplaceAll([]byte(translated), []byte("\"")))
	reg = regexp.MustCompile(`&gt;`) //fix >
	translated = string(reg.ReplaceAll([]byte(translated), []byte(">")))
	reg = regexp.MustCompile(`&lt;`) // fix <
	translated = string(reg.ReplaceAll([]byte(translated), []byte("<")))
	reg = regexp.MustCompile(`&#39;`) // fix '
	translated = string(reg.ReplaceAll([]byte(translated), []byte("'")))
	reg = regexp.MustCompile(` (\*) ([A-za-z0-9]+) (\*)`) // fix underline (*foo*)
	translated = string(reg.ReplaceAll([]byte(translated), []byte("$1$2$3")))

Brilliant. Becaues I never would have been able to write those Regular Expressions without serious help!

Conclusion

I hope you found these tools as helpful as I do. I really do use them on a near-daily basis for the work I do. I have them pinned as tabs in my browser so they are always open and easy to find.

If you know of other tools, please do let me know! And don’t forget to follow me on Twitter!