Heim > Artikel > Backend-Entwicklung > Babyschritte mit Go
Ich beschloss, Go auf meiner Reise auszuprobieren, um eine neue Sprache zu lernen, die für meine Karriere und meine Interessen nützlich sein würde. Dieses Mal habe ich es mit Go versucht. Ich denke, was den ersten Eindruck betrifft, ist es ziemlich schön.
Dies ist keine geführte Tour und wohl auch nicht für jemand anderen als mich selbst geschrieben, als persönliche Erinnerung.
Ich habe mir dafür ein kleines Projekt namens Os-Release-Q gegeben. Meine Absicht war es, auf jedem von mir verwalteten System eine Binärdatei zu haben, sodass ich genau die Informationen ausdrucken kann, die ich benötige, ohne sie analysieren oder mit den Augen danach suchen zu müssen.
Bei der Suche im Internet geht es viel um das Importieren der Pakete anderer Leute, aber sehr wenig um die Organisation des eigenen Codes. Sogar die Dokumente konzentrieren sich eher auf Go Get als auf die Trennung von Bedenken.
Ich stoße in jeder Sprache ziemlich häufig auf diese Hürde, da jede ihre eigene, eigenwillige Philosophie hat, wie man damit umgeht und welche Einschränkungen jede hat oder auferlegt.
Von all den Aktivitäten, die ich unternommen habe, um die Grundlagen zu erlernen, da ich überwiegend einen Python-Hintergrund habe, dauerte es am längsten, bis ich Antworten auf die Frage bekam, meinen Code in mehrere Dateien aufzuteilen. Zusammenfassend habe ich Folgendes gefunden:
Bei lokalen Submodulen muss sich das Submodul in einem Ordner befinden. Es kann einen Paket-Submodulnamen deklarieren.
Angenommen, es befindet sich in src/submod/, mit dem Hauptimplementierer in src/submod/submod.go. In main.go importieren wir „module-name/src/submod“ (wobei der Modulname aus go.mod gezogen wird). Und dann können wir submod.SomeFunction().
aufrufenWir beachten, dass Submodulfunktionen nur für Importeure verfügbar sind, wenn ihr Name mit einem Großbuchstaben beginnt. Also kein submod.myFunction() – es muss submod.MyFunction() sein.
Es gibt sicherlich noch andere Überlegungen zu Submodulen und Importen, aber was die Organisation und Trennung des Codes angeht, ist dies das Wesentliche.
Um die Dinge vernünftig zu halten, habe ich versucht, nur eine Datei zu haben, die das Hauptpaket deklariert, und den Rest in Submodule zu isolieren – diese werden automatisch importiert, ohne dass sie in der Dateiliste von go build FILES deklariert werden müssen.
Nachdem ich diese Besonderheit von Go geklärt hatte, ergab sich der Rest ganz einfach. Für jede grundlegende Aufgabe gab es natürlich einen StackOverflow-Eintrag oder eine GoByExample.com-Seite und im Grunde genommen die Go-Sprachreferenz.
Zwei besonders häufige Aufgaben verdienen eigene Absätze.
Die grundlegende Fehlerbehandlung wird oft als umständlich bezeichnet, da Fehler buchstäblich mitten im Kontrollfluss behandelt werden müssen. Dies mag für Programmierer, die einen Try/Catch-Workflow nutzen, ein Gräuel sein, aber das Problem an dem Punkt zu behandeln, an dem es auftreten kann, ist nicht so schlimm.
// explicit return item `err` forces us to be aware of it // but having the ability to check it in the same breath is not so bad if result, err := someCall(); err != nil { log.Fatal("Sorry.") } // Equally valid is /* result, err := someCall() if err != nil { log.Fatal("Sorry") } */ fmt.Println(result)
Try/Catch-Methode vergleichen
try: result = someCall() print(result) except: print("Sorry") # a little divorced from potential origin of error sys.exit(1)
Ich komme nicht umhin, das Gefühl zu haben, dass die Implementierung der Flags-Bibliothek etwas unausgegoren ist. Offensichtlich sind die Menschen daran gewöhnt und damit einverstanden, wenn man bedenkt, dass es in seiner jetzigen Form überlebt.
Der Aufruf des Programms -flag arg1 arg2 gibt uns den Schalter, für den das Flag eingerichtet ist, und positionals := flags.Args() gibt uns das Array von ["arg1", "arg2"] zurück
Der Aufruf des Programms arg1 arg2 -flag schaltet jedoch nicht um, was -flags tun soll, und gibt stattdessen Positionsangaben als ["arg1", "arg2", "-flag"] aus, wobei das Flag wurde nicht analysiert.
Dies kann nützlich sein, um einen Unteraufruf wie das Programm colorize ls -l zu übergeben, bei dem ls -l wörtlich weitergegeben wird – damit ich einen Anwendungsfall erkennen kann.
Es ist nur so, dass die meisten Programme Flag-Argumente überall in der Nähe von Positionselementen zulassen. ls dir1/ -l dir2/ ist dasselbe wie ls -l dir1/ dir2/, und diese Konvention gilt für die überwiegende Mehrheit der Unix- und Linux-Befehle.
Vielleicht ist das einfach gewöhnungsbedürftig – und es lohnt sich, darauf hinzuweisen.
Abgesehen vom Dateiimport-Paradigma fand ich es ziemlich einfach, meine Basisanwendung zu implementieren. Alles, was ich falsch gemacht habe, fühlte sich ziemlich offensichtlich an und die Fehler waren bedeutsam. Es fühlt sich wirklich so an, als ob ich mich einfach darauf konzentrieren kann, „Dinge zu erledigen“.
Anhand meiner bisher sehr geringen Nutzungsmenge und unter Berücksichtigung meiner spezifischen Bedürfnisse kann ich sehen
Ich dachte, spärliche Typen anstelle von Objekten und Vererbung wären ein Hindernis, aber soweit so gut. In anderen Sprachen komme ich ohne sie aus. Wenn ich also dazu komme, Schnittstellen und Typen zu definieren, wird es sich wie ein Fortschritt gegenüber Lua und Bash anfühlen. Ich hoffe.
Einer der Gründe, warum ich eine in die native Sprache kompilierte Sprache erforschen wollte, bestand darin, Binärdateien erstellen zu können, die leicht verschoben werden können, ohne dass eine bestimmte Version einer Laufzeitumgebung vorhanden sein muss.
Ein Kollege kam kürzlich bestürzt an meinen Schreibtisch und versuchte, eine Lösung zu finden, um Java 17 auf ein altes Node-Basisimage zu bringen, das auf Debian 10 basierte. Entweder müsste er die Node-Version aktualisieren, um ein neueres Basis-Image zu erhalten, ein neues Debian-Basis-Image verwenden und Node manuell installieren und konfigurieren, oder er müsste das Internet nach einem benutzerdefinierten Repo durchsuchen, das von Gott weiß wer gehostet wird -falls Java 17 gehackt wurde, das unter Debian 10 laufen würde.
Wie viel einfacher wäre es, wenn die bereitgestellte Software keine derart widersprüchlichen Laufzeitabhängigkeiten hätte...
Aus betrieblicher Sicht besteht meiner Meinung nach der einzige große Vorteil darin, dass ich problemlos Code schreiben und eine ELF-Binärdatei erstellen kann, um sie dann auf dem „beliebigen System X“ bereitzustellen, ohne mich damit auseinandersetzen zu müssen Sicherstellen, dass die richtige Version einer bestimmten Laufzeit vorhanden ist, und Verwalten widersprüchlicher Abhängigkeiten.
Ich bin mir sicher, dass es noch weitere Vorteile gibt, und ich habe viel über die Benutzerfreundlichkeit von Multithreading und Multiprocessing in Go gehört, und ich habe vor, als nächsten Schritt ein Miniprojekt auszuarbeiten, um das zu erkunden – wahrscheinlich etwas, das auf Eingaben auf mehreren Kanälen lauscht und als Reaktion darauf einige grundlegende Aufgaben ausführt. Ich hatte in einigen Testautomatisierungsaufgaben, die ich zuvor hatte, einen Anwendungsfall dafür, daher ist es mir zu diesem Zeitpunkt nicht fremd.
Das obige ist der detaillierte Inhalt vonBabyschritte mit Go. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!