Go: x/vgo: Das go.mod-Format sollte keine maßgeschneiderte Syntax haben

Erstellt am 21. Feb. 2018  ·  30Kommentare  ·  Quelle: golang/go

Es ist ein Fehler, eine private Syntax für eine Konfigurationsdatei zu erstellen, wenn existierende, perfekte Formate verfügbar sind, die gut verstanden werden und über öffentlich verfügbare Parser verfügen.

FrozenDueToAge

Hilfreichster Kommentar

Ich denke, wir sollten nach der weiteren Vereinfachung der optionalen Anführungszeichen (#24641) weiterhin das sehr einfache go.mod-Format verwenden. Sobald sich der Staub gelegt hat, sollten wir auch ein Paket wie x/vgo/vendor/cmd/go/internal/modfile veröffentlichen, damit andere Tools auch Mod-Dateien analysieren und bearbeiten können.


Wie ich ursprünglich geschrieben habe, verstehe ich den Reiz eines Standarddateiformats, aber ich kann immer noch kein finden, das für diese Aufgabe gut funktioniert. Mein Hauptanliegen ist die einfache Bearbeitung, sowohl für Personen als auch für Programme.

Die Dateien müssen leicht zu bearbeiten sein. Zum Beispiel speichert das von mir erstellte gehackte Blog-Post-System einen JSON-Blob oben in jeder Datei über dem Post-Text, da dies sehr einfach zu implementieren war. Aber ich habe es satt, das Komma nach dem letzten Schlüsselwertpaar weglassen zu müssen, da das Hinzufügen eines neuen Schlüsselwerts dazu führt, dass auch der vorherige bearbeitet wird. Genau aus diesem Grund erlauben wir nachfolgende Kommas in Go-Literalen. Diese Ärgernisse summieren sich.

Die Dateien müssen auch für Programme leicht zu bearbeiten sein, ohne sie zu verstümmeln. Denken Sie an all die Vorteile, die wir von gofmt und den Tools erhalten haben, die in der Lage sind, mit Leuten zusammenzuarbeiten, um an Go-Quelldateien zu arbeiten. Menschen und Programme, die an go.mod zusammenarbeiten, werden ähnlich nützlich sein. Tatsächlich ist dies ein wichtiger Teil des Designs. Wenn Sie die Tour von Versioned Go durchlesen, werden Sie immer wieder einen Wechsel zwischen dem Entwickler, der go.mod bearbeitet, und dem vgo selbst, der go.mod bearbeitet, sehen. Das muss ganz flüssig laufen.

Alle Formate des „generalisierten Schlüssel-Wert-Paares“ werden umständlich, wenn mehr als ein einzelnes Schlüssel-Wert-Paar ausgedrückt werden muss. Es stimmt, dass wir eine YAML-ähnliche Notation verwenden könnten:

module: rsc.io/hello
require: 
- golang.org/x/text: v0.0.0-20180208041248-4e4a3210bb54
- rsc.io/quote: v1.5.2

aber diese nette zeilenweise Pause, wenn wir bei replace "rsc.io/quote" v1.5.2 => "../quote" . Die vielleicht beste Kodierung wäre:

replace:
- rsc.io/quote: v1.5.2
  with: ../quote

Aber als was kodiert replace "rsc.io/quote" v1.5.2 => "github.com/you/quote" v0.0.0-myfork ? Vielleicht das?

replace:
- rsc.io/quote: v1.5.2
  with: github.com/you/quote
  at: v0.0.0-myfork

Die Umständlichkeit ist hier nicht groß, aber dennoch ziemlich nervig: drei Zeilen statt einer, mit entsprechend eingeschränkter Lesbarkeit und Möglichkeit, zeilenbasierte Tools wie grep, sort, diff zu verwenden.

Das grundlegende Problem besteht darin, dass nicht alles, was ein Entwickler zu sagen hat, am besten als Schlüssel-Wert-Paare ausgedrückt werden kann. Wir verwenden keine Shells, für die wir Folgendes schreiben müssen:

cmd:
- prog: echo
- arg1: hello
- arg2: world

Aber irgendwie akzeptieren viele Entwickler dies in Konfigurationsdateien. Wieso den? Denn, wie Rob sagte, existierende Formate „sind gut verstanden und verfügen über öffentlich verfügbare Parser“. Zumindest glauben wir, dass das stimmt. Je mehr ich mir diese Formate anschaue, desto weniger überzeugt bin ich. Und selbst unter der Annahme, dass dieser Nutzen die Nachteile des Formats selbst überwiegen muss.

JSON ist zu wählerisch (z. B. bei Kommas) und unterstützt keine Kommentare. Es ist aus.

XML ist beim Schließen von Tags ebenso wählerisch und im Allgemeinen zu laut. Es ist aus.

TOML und YAML sind für Benutzer zumindest einfacher zu bearbeiten, haben aber beide das allgemeine Schlüsselwertproblem.

Darüber hinaus erfordert TOML Anführungszeichen um beide Modulpfade als Schlüssel (da sie Schrägstriche haben) und alle Werte ( "rsc.io/quote" = "v1.5.2" ). Die Erfahrung mit go.mod legt nahe, dass wir uns in die entgegengesetzte Richtung bewegen wollen, in Richtung auf keine Anführungszeichen. (Siehe #24641.)

Sowohl TOML als auch YAML erweisen sich außerdem als komplexer, als sie auf den ersten Blick erscheinen, ein Detail, das sehr wichtig ist, wenn Sie nicht nur einen Parser, sondern einen mechanischen Editor benötigen, der die Datei parsen, bearbeiten und erneut drucken kann. Die Komplexität von TOML zeigt sich, sobald Sie sich von Schlüssel-Wert-Paaren entfernen: Sie müssen den Unterschied zwischen [x] und [[x]] lernen und dann anfangen, über reguläre Schlüssel-Wert-Paar-Zeilen im Vergleich zu Inline-Tabellen nachzudenken. Das ist natürlich nichts im Vergleich zu YAML. Hier ist eine aufschlussreiche Übung: Blättern Sie durch http://yaml.org/spec/1.2/spec.pdf und versuchen Sie herauszufinden, welche syntaktischen Einschränkungen für Schlüssel und Werte ohne Anführungszeichen in Schlüssel-Wert-Paaren gelten. Ich bin mir immer noch nicht ganz sicher. YAML bettet JSON als Teilmenge ein, aber hier hört es noch nicht auf. Soweit ich dem Dokument entnehmen kann, anstatt zu schreiben:

module: rsc.io/hello
require: 
- golang.org/x/text: v0.0.0-20180208041248-4e4a3210bb54
- rsc.io/quote: v1.5.2

es scheint ebenso gültig zu sein, zu schreiben:

%YAML 1.2
---
!!map {
 ? !!str "module" : !!str "rsc.io/hello"
 ? !!str "require" 
 : !!seq [
   !!map { ? !!str "golang.org/x/text" : !!str "v0.0.0-20180208041248-4e4a3210bb54" },
   !!map { ? !!str "rsc.io/quote" : !!str "v1.5.2" },
 ],
}

und es scheint auch, dass die beiden Formen willkürlich vermischt werden können. So einfach wie

module: !!str rsc.io/hello

scheint gültiges YAML zu sein, bedeutet jedoch etwas anderes als das, was unser "Teilmengen"-Parser verstehen würde. Es würde ständig Druck geben, das Beharren auf der Verwendung einer Teilmenge von YAML aufzugeben, und dennoch wird es schwieriger, einen guten mechanischen Editor (Parse+Edit+Reprint) zu schreiben, je komplexer die Einführung ist.

Wenn wir ein vorhandenes Format auswählen müssten, würde ich TOML wählen, aber selbst das scheint falsch zu sein:

module = "rsc.io/hello"

[require]
"golang.org/x/text" = "v0.0.0-20180208041248-4e4a3210bb54"
"rsc.io/quote" = "v1.5.2"

[[replace]]
"rsc.io/quote" = "v1.5.2"
with = "github.com/you/quote"
at = "v0.0.0-myfork"

Die [[ ]] sind hier notwendig, weil [require] eine einzelne Tabelle ist (von Schlüssel-Wert-Paaren, von denen jedes für sich steht), während [[replace]] ein Array von Tabellen ist, in denen jede Tabelle ein Ersatz mit drei ist Schlüssel: der zu ersetzende Pfad und die Sonderschlüssel „mit“ und „at“. Wenn Sie eine mögliche zukünftige Erweiterung reservieren möchten, müssen Sie auch [[erforderlich]] verwenden.

[[require]]
"golang.org/x/text" = "v0.0.0-20180208041248-4e4a3210bb54"

[[require]]
"rsc.io/quote" = "v1.5.2"

Alles in allem scheint es, als würden diese Dateiformate nicht wirklich dazu beitragen, unser Ziel zu erreichen, die Datei für Benutzer und Programme einfach zu bearbeiten. Wir müssten wahrscheinlich sowieso einen benutzerdefinierten Parser + Nachdrucker schreiben, daher wäre der einzige wirkliche Vorteil die Syntaxhervorhebung in Editoren. Ich denke, dieser Vorteil wird leicht durch die Unbeholfenheit aufgewogen, unsere Semantik überhaupt in diese Dateien zu stecken. Wenn Ihre Konfiguration aus wenigen grundlegenden Schlüssel-Wert-Paaren besteht, sind diese sehr sinnvoll. Wir haben nicht nur Schlüssel-Wert-Paare, daher machen diese Dateien keinen Sinn.

PS Ich habe mich lange gefragt, warum "dep secure -add" bestehende Einschränkungen in Gopkg.toml nicht geändert hat. Die Antwort ist, dass Dep handgeschriebenes TOML nicht zuverlässig modifizieren kann, um Kommentare und dergleichen zu erhalten. Dep hängt manchmal an Gopkg.toml an, erlegt aber ansonsten die Regel auf, dass Gopkg.toml im Besitz von Personen ist und Gopkg.lock im Besitz von Programmen ist. Dies scheint sowohl ein Artefakt der verfügbaren Bibliotheken als auch eine Designentscheidung zu sein.

Alle 30 Kommentare

PS Dieses Problem wird durch die seltsame Behauptung, dass das Format behoben ist, bevor jemand die Möglichkeit hat, es zu kommentieren, noch dornenreicher.

Meine Stimme ist für XML.

(Um es ernster zu nehmen: Es wäre schön, etwas zu haben, das von Menschen leicht zu schreiben ist. JSON ist leicht zu lesen, nervig zu schreiben. YAML ist in beide Richtungen gut.)

Vielleicht ist ein Teil dieses Dep-Threads aus dem letzten Jahr relevant: https://github.com/golang/dep/issues/119

https://github.com/hashicorp/hcl/blob/master/README.md

Erwähnt, dass YAML verwirrend und nicht gut verstanden ist. Ich verstehe es auch nicht besonders, wenn man bedenkt, dass Tabs standardmäßig nicht als Trennzeichen zulässig sind, was für eine Whitespace-agnostische Sprache wie Go ungewöhnlich und umständlich ist.

http://www.yaml.org/faq.html

Es fällt mir sehr schwer, "yaml" und "perfektes Format" in Einklang zu bringen. Es ist nicht die Beschreibung, die mir nach meiner Erfahrung in den Sinn kommt.

Ein Vorteil eines benutzerdefinierten Formats besteht darin, dass nur zulässig ist, was zulässig ist. Eine andere ist, dass man allem eine schöne ausdrucksvolle Syntax geben kann. Fehlermeldungen können einfacher angepasst werden.

Die Ähnlichkeit mit der Go-Syntax bedeutet, dass es für niemanden schwer sein sollte, sie zu erlernen, und Syntax-Highlighter und dergleichen sollten leicht von ihren Go-Gegenstücken angepasst werden können.

Der einzige große Nachteil, den ich sehe, ist, dass seine Implementierung als neues Format eine gewisse Menge an Fuzzing und zusätzliche Tests erfordert, die sonst (hoffentlich) bereits durchgeführt würden. (Und wenn der Parser in die stdlib gestellt wird, muss sich auch sonst niemand darum kümmern).

...warum nicht einfach Go geschrieben werden?

Ich meine, wir alle wissen, wie man es schreibt. Wir haben gut getestete Lexer und Parser. Wir haben Syntax-Highlighting. Wir haben Formatierer und Tools, die den Code überprüfen können. Wir haben sogar ein Framework zum Parsen und Ausführen von Dateigruppen in go test .

Diese go.mod Datei

// My hello, world.

module "rsc.io/hello"

require (
    "golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54
    "rsc.io/quote" v1.5.2
)

könnte so etwas werden

package foobar

import vgo

func ModuleHelloWorld(v *vgo.V) {
    v.Module("rsc.io/hello")
    v.Require("golang.org/x/text", "v0.0.0-20180208041248-4e4a3210bb54")
    v.Require("rsc.io/quote", "v.1.5.2")
}

Es würde am Ende ähnlich sein, wie go test xxx_test.go Dateien erkennt.

vgo könnte eine go.mod , module , xxx_module.go oder eine andere Datei im Stammverzeichnis des Projekts erkennen und die Top-Level-Funktion ähnlich wie ModuleXXX ausführen TestXXX .

Ja, es fühlt sich nicht so sehr wie eine Reihe von Direktiven an wie ausführbarer Code, aber seit wann hat Go etwas getan, damit es sich gut anfühlt und nicht wie die praktische Option?

Theoretisch könnte sich das auch um https://github.com/golang/go/issues/23972 . kümmern

Lassen Sie uns nicht wissen, welches vorhandene Format am besten geeignet ist, und warten wir auf eine Antwort, warum überhaupt eine benutzerdefinierte Syntax gewählt wurde. Es kann eine willkürliche Entscheidung gewesen sein oder auch nicht. Wenn dies nicht der Fall war, wird das Verständnis der Entscheidung dazu beitragen, zukünftige Entscheidungen zu treffen.

Die meisten Leute haben sich für TOML entschieden. Wir brauchen nicht wirklich ein anderes benutzerdefiniertes Format oder ein in JSON oder YAML eingebettetes Format.

Da die go.mod-Datei einer go-Quelldatei sehr ähnlich sieht, warum nicht module and require als Deklarationen der obersten Ebene hinzufügen und dann können wir die Modulsyntax inline mit unserem Quellcode schreiben?

Am 21. Februar 2018 um 15:58 Uhr schrieb David Karapetyan [email protected] :

Die meisten Leute haben sich für TOML entschieden. Wir brauchen nicht wirklich ein anderes benutzerdefiniertes Format oder ein in JSON oder YAML eingebettetes Format.


Sie erhalten dies, weil Sie diesen Thread abonniert haben.
Antworten Sie direkt auf diese E-Mail, zeigen Sie sie auf GitHub an oder schalten Sie den Thread stumm.

Tatsächlich habe ich sofort gespürt, wie die Tour mit mod.go statt go.mod probiert wurde!

@davecheney Ich denke, die Datei go.mod macht es einfach, das Projektstammverzeichnis zu finden. Wenn module und require in "normalen" .go-Dateien zu Deklarationen der obersten Ebene werden, dann wäre es schwieriger, das Projekt-Root zu finden (Sie mussten im Grunde nach einer .go-Datei suchen, die eine module Deklaration, die ein Parsen erfordert).

Das Problem mit TOML und YAML besteht darin, dass niemand Code (AFAIK) geschrieben hat, der diese Formate (einschließlich Kommentare) lesen und sie im Gofmt-Stil wieder ausschreiben kann. Siehe zum Beispiel https://github.com/BurntSushi/toml/issues/213 . Außerdem ist YAML ein schreckliches Format. Bitte kein YAML.

Ich denke, ich mag die Wahl eines benutzerdefinierten Formats sehr, solange es eine einfache Möglichkeit gibt, in ein/aus einem bekannten Format zu konvertieren, weil es so einfach wie nötig und so sauber wie möglich sein kann.

Was auch immer das Format ist, es muss gut definiert und gut dokumentiert sein, mit einer kanonischen Formatierung und nicht-internen Bibliotheken, um es zu lesen und zu schreiben. Nichts davon existiert im Moment.

Ich trete hier sehr ungern ein. Mir gefällt, was ich bisher von vgo sehe, und ich möchte nicht auf ein triviales Thema eingehen.

Ich habe jedoch das Gefühl, dass ein Teil der Reibungen, die ich bei meinen ersten vgo-Experimenten spüre, von den restlichen Tools herrührt, die ich verwende, um Go zu schreiben und mit Code im Allgemeinen zu arbeiten. Ich denke, dies ist eine Gelegenheit, die Adoption ein wenig zu erleichtern.

Aus diesem Grund sollten wir meiner Meinung nach in Betracht ziehen, ein vorhandenes gemeinsames Datenformat zu übernehmen:

Motivationen

  • Editor/Viewer-Unterstützung. Redakteure wissen bereits, wie man Syntaxhervorhebungen, Formatierungen usw. für Standarddatenformate durchführt. Schauen Sie sich sogar die Codeschnipsel in diesem Thread an. GitHub kann go.mod Snippets nicht parsen und hervorheben, aber wir haben ein gemeinsames Datenformat gewählt, es würde einfach sofort funktionieren. Lassen Sie uns GitHub, die Editor-Autoren und den Rest nicht dazu bringen, einen speziellen Parser nur für diesen einen Dateityp zu implementieren und zu pflegen.
  • Toolchain-Unterstützung . Ob innovative Tools wie Greenkeeper oder Standbys wie Artifactory, es gibt viele gute Gründe, die Abhängigkeiten eines Projekts zu analysieren. Intern haben wir einen Scraper geschrieben, um die Abhängigkeiten verschiedener Teams voneinander zu überprüfen und mit Querverweisen zu versehen. Es ist ganz einfach, Dateien wie package.json npm aufzunehmen – es ist nur JSON! -- und wir könnten es von jeder Sprache aus tun. Es gibt viele Aufgaben zur Abhängigkeitsverwaltung, die automatisiert werden müssen. Ein Standarddatenformat macht es viel einfacher, vgo-Unterstützung hinzuzufügen und könnte dazu beitragen, dass es sich schneller im Ökosystem verbreitet.
  • Vertrautheit . Love 'em or hasse 'em, JSON und YAML sind heutzutage bekannte Formate für Entwickler. Wir lösen keine Probleme mit ihnen, indem wir ein neues Format einführen, wir bringen die Leute nur dazu, ein weiteres Dateiformat zu lernen.
  • Erweiterbarkeit . Ich habe gesehen, wie die Liste der VGO-Funktionsanfragen gerade am ersten Tag gewachsen ist, und ich kann mir nur vorstellen, wohin wir als nächstes gehen. Bei YAML oder JSON ist dies nur ein weiterer Schlüsselwertsatz. Bei go.mod müssen wir uns für einen maßgeschneiderten Ort entscheiden, um es in der Datei abzulegen – und dann alle Parser, Syntax-Highlighter und andere Werkzeuge in der restlichen Werkzeugkette aktualisieren.

Anforderungen

Ich habe keine starken Gefühle gegenüber YAML vs. JSON vs. was auch immer. Ich habe JSON gut mit npm und YAML gut mit Kubernetes, Helm und Ansible verwendet. Sie funktionieren beide, und ich bin lange über den Punkt in meiner Karriere hinaus, an dem ich mich für solche Argumente interessiere. (Und was es wert ist, ich habe mich nie durch das Fehlen von Inline-Kommentaren gestört – READMEs und Issues haben in den seltenen Fällen funktioniert, in denen wir über Abhängigkeiten kommunizieren mussten.) Von meinem Standpunkt aus sind die Anforderungen:

  • In den gängigsten Sprachen implementierte Parser.
  • Bestehende Editor- und Tooling-Unterstützung von Dingen wie GitHub selbst.
  • Hierarchisch. Zum Beispiel sind .properties Dateien zu restriktiv für zukünftige Erweiterungen.

Entschuldigung im Voraus, wenn ich nicht am Stützpunkt bin. Ich bin selbst ziemlich neu bei Go und gestehe, dass ich einige der ursprünglichen Beweggründe für ein maßgeschneidertes Dateiformat noch nicht verstehe. Es mag gute Gründe geben, eine andere Richtung einzuschlagen, die ich übersehe!

@ecowden

Hierarchisch. Zum Beispiel schränken .properties-Dateien die zukünftige Erweiterung zu stark ein.

@rsc gibt in seinem Blog-Beitrag an, dass vgo eine Rationalisierung/Vereinfachung des Allzweck-Dep-Tools sein soll. Angesichts der Tatsache, dass dep sich ausdrücklich für TOML entschieden hat, auch weil es nicht hierarchisch war, scheint es unwahrscheinlich, dass vgo diese Anforderung rückgängig machen würde.

Von https://github.com/golang/dep/issues/119#issuecomment -287781062

Das einzige, was bei TOML auffällt, ist, dass wir keine Baumstruktur haben und es uns möglich ist, Einschränkungen an das Manifest anzuhängen, ohne es neu zu schreiben. Dies kann sich als sehr wichtiger Faktor bei der Anwendung vernünftiger Standardeinstellungen erweisen, die uns (d. h. das gesamte öffentliche Go-Ökosystem) vor einem exponentiellen Wachstum der Solver-Laufzeit schützen.

@ericlagergren Ich mag zwar die Einfachheit der Wiederverwendung der go-Syntax, aber die Verwendung der .go-Erweiterung für die Moduldatei macht es wahrscheinlich, dass einige Projekte in einen Konflikt geraten und einige ihrer Dateien umbenennen müssen, um zu vgo zu wechseln, was gegen das Ziel verstößt die Migration so schmerzlos wie möglich zu gestalten.

Der Dateiname ist nicht sehr zentral für die Idee, IMO.
Lemer. 21. Februar. 2018 à 08:05, Hugues [email protected] a écrit :

@ecowden https://github.com/ecowden

Hierarchisch. Zum Beispiel sind .properties-Dateien zu restriktiv, um
zukünftige Erweiterung.

@rsc https://github.com/rsc gibt in seinem Blogbeitrag an, dass vgo gemeint ist
eine Rationalisierung/Vereinfachung des universellen Dep-Tools sein. Gegeben
diese Abteilung hat sich explizit für TOML entschieden, auch weil es
war nicht hierarchisch, es scheint unwahrscheinlich, dass vgo das rückgängig machen würde
Erfordernis.

Von golang/dep#119 (Kommentar)
https://github.com/golang/dep/issues/119#issuecomment-287781062

Das einzige, was bei TOML auffällt, ist, dass es nicht baumstrukturiert ist,
Es ist uns möglich, Einschränkungen an das Manifest anzuhängen, ohne
es umschreiben. Das kann sich als sehr wichtiger Faktor bei der Bewerbung herausstellen
gesunde Standardeinstellungen, die uns helfen (d. h. das gesamte öffentliche Go-Ökosystem)
gegen ein exponentielles Wachstum der Solver-Laufzeit.

@ericlagergren https://github.com/ericlagergren Während ich das mag
einfache Wiederverwendung der go-Syntax durch Verwendung der .go-Erweiterung für das Modul
Datei macht es wahrscheinlich, dass einige Projekte in einen Konflikt geraten und
müssen einige ihrer Dateien umbenennen, um zu vgo zu wechseln, was gegen die
Ziel ist es, die Migration so schmerzlos wie möglich zu gestalten.


Sie erhalten dies, weil Sie erwähnt wurden.

Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/golang/go/issues/23966#issuecomment-367375465 oder stumm
der Faden
https://github.com/notifications/unsubscribe-auth/AFnwZ2Ni2oC28frH2klja-K6ywyOXBCgks5tXD6RgaJpZM4SM3IZ
.

Abgesehen von anderen Bedenken lässt JSON keine Kommentare zu, was ausreicht, um es IMO zu disqualifizieren.

Welches Format auch immer verwendet wird, ich hoffe (mit Rob) auf jeden Fall, dass es gute öffentliche Manipulationsbibliotheken gibt.

Hier einige Kommentare aus der jahrelangen Arbeit an goimports:

  • Der Umgang mit Kommentaren ist ein Albtraum. Ein Teil davon ist der Fehler von go/ast und go/printer, aber ein Teil davon ist konzeptionell – es ist oft nicht offensichtlich, was mit einem Kommentar passieren soll, wenn ein Import hinzugefügt, gelöscht oder verschoben wird.

  • Das aktuelle Format scheint einzelne und faktorisierte Formen zu akzeptieren. goimports hat sich nur noch auf Factoring-Formulare umgestellt. Dies hilft einigen bei Kommentaren und hält Diffs sauber. Außerdem wird es einfacher sein, Regexps für nur Factoring zu schreiben, und leider verwenden viele Editoren immer noch Regexps zum Hervorheben usw.

  • Gruppierungsregeln werden unweigerlich komplex (zB stdlib vs. Vendor vs. other), insbesondere wenn Sie versuchen, bestehende Gruppierungen zu respektieren.

Dieses Problem wird durch die seltsame Behauptung, dass das Format behoben ist, bevor jemand die Möglichkeit hat, es zu kommentieren, noch dornenreicher.

Mein Punkt, der wohl zu stark formuliert wurde, ist, dass go.mods-Leute, die heute schreiben, von den eventuellen offiziellen Tools verstanden werden. Ich möchte klarstellen, dass die Leute sie nicht wegwerfen und neu anfangen müssen. Da vgo bereits das Lesen von neun verschiedenen Legacy-Dateiformaten unterstützt (GLOCKFILE, Godeps/Godeps.json, Gopkg.lock, Dependencies.tsv, Glide.lock, Vendor.conf, Vendor.yml, Vendor/manifest, Vendor/vendor.json) , Ich bin zuversichtlich, dass es keine Last sein wird, auch dieses zu lesen, wenn wir zu etwas Neuem übergehen. Und die Tools schreiben go.mod bei Bedarf bereits um, sodass die Aktualisierung auf ein neues Format einfach ist, wenn wir dies entscheiden. Ich habe nicht versucht, dies zu sperren.

Es ist ein Fehler, eine private Syntax für eine Konfigurationsdatei zu erstellen, wenn existierende, perfekte Formate verfügbar sind, die gut verstanden werden und über öffentlich verfügbare Parser verfügen.

Dem stimme ich natürlich grundsätzlich zu. In der Praxis habe ich mir eine Weile alle vorhandenen Formate angeschaut und fand sie für diesen Job nicht "vollkommen in Ordnung". Schauen Sie sich insbesondere an, wie viel kürzer und übersichtlicher eine go.mod im Vergleich zur entsprechenden Gopkg.toml ist. Ich komme gerne auf diese Frage zurück, sobald wir mit allen anderen höherwertigen Details zufrieden sind.

Und um die Bedenken von @josharian zu beantworten: Wenn wir das benutzerdefinierte Format

Ich mag die Vorschläge von @ericlagergren und @davecheney. Es nutzt den gesamten go Compiler und seine Garantien. Aber da go.mod gut ist, um den Paketstamm zu erkennen, habe ich ein paar Vorschläge, um diesen Vorteil beizubehalten, während man sich im Quellcode zu Modulen bewegt:

__Vorschlag 1__

Haben Sie Inline-Modulinformationen zu main.go für Binärdateien und lib.go für Bibliotheken.

Rust verwendet main.rs vs lib.rs , um Binärdateien von Bibliotheken zu unterscheiden, und hat ein Cargo.toml im Projektstamm. Der Unterschied besteht darin, dass die Modulinformationen bei diesem Vorschlag die Go-Syntax in einer Go-Quelldatei verwenden würden.

__Vorschlag 2__

Verwenden Sie mod.go sowohl für Binärdateien als auch für Bibliotheken, und fügen Sie dann vgo.Product = "binary" // or "library" oder eine Art const iota anstelle von Strings hinzu.

Swift hat einen Package.swift , der ein gültiger Swift-Code im Projektstamm ist, der angibt, ob es sich um eine Binärdatei oder eine Bibliothek mit dem Package.products Typ handelt, der .library oder .executable

BEARBEITEN: Vergleich zu den obigen Vorschlägen hinzugefügt.

@huguesb

rsc gibt in seinem Blog-Beitrag an, dass vgo eine Rationalisierung/Vereinfachung des Allzweck-Dep-Tools sein soll...

Ich bin neugierig: Warum bedeutet „hierarchisch“ „komplex“?

Zurücktretend, ich habe diese letzte Anforderung wahrscheinlich falsch formuliert. Ich war auf der Suche nach einer Schnittstelle zwischen dem Vertrauten und dem Erweiterbaren und habe dabei YAML und JSON im Kopf. „Hierarchisch“ ist hier nicht wirklich das Ziel, und ich streiche es gerne von der Liste.

Ich bin jedoch überrascht zu sehen, wie komplex die Reaktion ist, und frage mich, ob ich etwas übersehe. Wenn ich mir das Beispiel von mod.go Dateien wie dieser anschaue...

module "rsc.io/hello"

require (
    "golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54
    "rsc.io/quote" v1.5.2
)

...ich persönlich sehe eine „hierarchische“ Datenstruktur. Damit meine ich eine Liste von Schlüssel-Wert-Paaren, wobei Werte Primitive, Listen oder andere Listen von Schlüssel-Wert-Paaren sein können. Ändern Sie nichts als Formatierung und Zeichensetzung, wird es zu:

module: rsc.io/hello
require: 
- golang.org/x/text: v0.0.0-20180208041248-4e4a3210bb54
- rsc.io/quote: v1.5.2

…Und es ist sogar 4 Zeichen kürzer! (Das ist ein Witz, wenn es nicht offensichtlich ist. :grins:)

Als ich hier einstieg, dachte ich darüber nach, einen vorhandenen Git-Repo-Abhängigkeitsanalysator, der in Node.js geschrieben wurde, zu erweitern, um vgo-Module zu erkennen. (Nun, das, und wie ich die schönen Farben vermisste, die mein Editor hervorhebt...) Dann wurde mir klar, wie sehr ich keinen benutzerdefinierten Parser erstellen und pflegen wollte und wie viel einfacher es mit einem "Standard" wäre " Datei Format.

Stellen Sie diese Frage auf jeden Fall zurück. Es gibt waaay wichtigere Dinge, die man mit vgo herausfinden muss, und was ich bisher sehe, gefällt mir! :+1:

Auch wenn YAML als zu komplex oder verwirrend angesehen wird, würde ich es (oder JSON oder TOML oder ein anderes deklaratives Standardformat) einem maßgeschneiderten Format vorziehen und die _Teilmenge_ davon unterstützen, mit der wir zufrieden sind.

Mit anderen Worten, wenn go.mod ein gültiges YAML/TOML/JSON ist (das nicht unbedingt alle Funktionen dieser Formate unterstützt), würde es sowohl Benutzern als auch jeder Plattform, die Sie zum Parsen verwenden möchten, sofort vertraut machen.

Das obige Beispiel von

Ein weiteres Problem bei go.mod ist, dass es nicht einmal deklarativ oder standardisiert aussieht, sondern wie ein zwingender Code. Gibt es dafür einen Grund? Wollen wir es eigentlich erweiterbar machen und dort zwingende Konstruktionen unterstützen, zB Funktionen?

@nilebox go.mod sieht nicht "imperativer" oder "deklarativer" aus als beispielsweise eine nginx-Konfigurationsdatei.

Vielleicht setze go.mod als Kommentar in die go-Datei. Beispielsweise:

/*
+require "golang.org/x/text" v0.0.0-20180208041248-4e4a3210bb54
+require "rsc.io/quote" v1.5.2
*/
package main // import "rsc.io/hello"

Oder

package main // import "rsc.io/hello"

import (
    "golang.org/x/text" // require v0.0.0-20180208041248-4e4a3210bb54
    "rsc.io/quote" // require v1.5.2
)

amiga-sound

Schade, dass mein Betriebssystem (ubuntu) denkt, dass die Datei go.mod eine Audiodatei ist. Das bedeutet, dass ich nicht einfach auf die Datei doppelklicken und sie bearbeiten kann, sondern mir die Mühe machen muss, meinem Betriebssystem mitzuteilen, dass *.mod-Dateien in einem Editor geöffnet werden sollen.

Sie können die Dateizuordnungen vollständig vom Benutzer ändern. Die Verwendung einer etablierten Erweiterung für die vgo-Moduldatei ist jedoch eine eher unglückliche Wahl.

Ich denke, wir sollten nach der weiteren Vereinfachung der optionalen Anführungszeichen (#24641) weiterhin das sehr einfache go.mod-Format verwenden. Sobald sich der Staub gelegt hat, sollten wir auch ein Paket wie x/vgo/vendor/cmd/go/internal/modfile veröffentlichen, damit andere Tools auch Mod-Dateien analysieren und bearbeiten können.


Wie ich ursprünglich geschrieben habe, verstehe ich den Reiz eines Standarddateiformats, aber ich kann immer noch kein finden, das für diese Aufgabe gut funktioniert. Mein Hauptanliegen ist die einfache Bearbeitung, sowohl für Personen als auch für Programme.

Die Dateien müssen leicht zu bearbeiten sein. Zum Beispiel speichert das von mir erstellte gehackte Blog-Post-System einen JSON-Blob oben in jeder Datei über dem Post-Text, da dies sehr einfach zu implementieren war. Aber ich habe es satt, das Komma nach dem letzten Schlüsselwertpaar weglassen zu müssen, da das Hinzufügen eines neuen Schlüsselwerts dazu führt, dass auch der vorherige bearbeitet wird. Genau aus diesem Grund erlauben wir nachfolgende Kommas in Go-Literalen. Diese Ärgernisse summieren sich.

Die Dateien müssen auch für Programme leicht zu bearbeiten sein, ohne sie zu verstümmeln. Denken Sie an all die Vorteile, die wir von gofmt und den Tools erhalten haben, die in der Lage sind, mit Leuten zusammenzuarbeiten, um an Go-Quelldateien zu arbeiten. Menschen und Programme, die an go.mod zusammenarbeiten, werden ähnlich nützlich sein. Tatsächlich ist dies ein wichtiger Teil des Designs. Wenn Sie die Tour von Versioned Go durchlesen, werden Sie immer wieder einen Wechsel zwischen dem Entwickler, der go.mod bearbeitet, und dem vgo selbst, der go.mod bearbeitet, sehen. Das muss ganz flüssig laufen.

Alle Formate des „generalisierten Schlüssel-Wert-Paares“ werden umständlich, wenn mehr als ein einzelnes Schlüssel-Wert-Paar ausgedrückt werden muss. Es stimmt, dass wir eine YAML-ähnliche Notation verwenden könnten:

module: rsc.io/hello
require: 
- golang.org/x/text: v0.0.0-20180208041248-4e4a3210bb54
- rsc.io/quote: v1.5.2

aber diese nette zeilenweise Pause, wenn wir bei replace "rsc.io/quote" v1.5.2 => "../quote" . Die vielleicht beste Kodierung wäre:

replace:
- rsc.io/quote: v1.5.2
  with: ../quote

Aber als was kodiert replace "rsc.io/quote" v1.5.2 => "github.com/you/quote" v0.0.0-myfork ? Vielleicht das?

replace:
- rsc.io/quote: v1.5.2
  with: github.com/you/quote
  at: v0.0.0-myfork

Die Umständlichkeit ist hier nicht groß, aber dennoch ziemlich nervig: drei Zeilen statt einer, mit entsprechend eingeschränkter Lesbarkeit und Möglichkeit, zeilenbasierte Tools wie grep, sort, diff zu verwenden.

Das grundlegende Problem besteht darin, dass nicht alles, was ein Entwickler zu sagen hat, am besten als Schlüssel-Wert-Paare ausgedrückt werden kann. Wir verwenden keine Shells, für die wir Folgendes schreiben müssen:

cmd:
- prog: echo
- arg1: hello
- arg2: world

Aber irgendwie akzeptieren viele Entwickler dies in Konfigurationsdateien. Wieso den? Denn, wie Rob sagte, existierende Formate „sind gut verstanden und verfügen über öffentlich verfügbare Parser“. Zumindest glauben wir, dass das stimmt. Je mehr ich mir diese Formate anschaue, desto weniger überzeugt bin ich. Und selbst unter der Annahme, dass dieser Nutzen die Nachteile des Formats selbst überwiegen muss.

JSON ist zu wählerisch (z. B. bei Kommas) und unterstützt keine Kommentare. Es ist aus.

XML ist beim Schließen von Tags ebenso wählerisch und im Allgemeinen zu laut. Es ist aus.

TOML und YAML sind für Benutzer zumindest einfacher zu bearbeiten, haben aber beide das allgemeine Schlüsselwertproblem.

Darüber hinaus erfordert TOML Anführungszeichen um beide Modulpfade als Schlüssel (da sie Schrägstriche haben) und alle Werte ( "rsc.io/quote" = "v1.5.2" ). Die Erfahrung mit go.mod legt nahe, dass wir uns in die entgegengesetzte Richtung bewegen wollen, in Richtung auf keine Anführungszeichen. (Siehe #24641.)

Sowohl TOML als auch YAML erweisen sich außerdem als komplexer, als sie auf den ersten Blick erscheinen, ein Detail, das sehr wichtig ist, wenn Sie nicht nur einen Parser, sondern einen mechanischen Editor benötigen, der die Datei parsen, bearbeiten und erneut drucken kann. Die Komplexität von TOML zeigt sich, sobald Sie sich von Schlüssel-Wert-Paaren entfernen: Sie müssen den Unterschied zwischen [x] und [[x]] lernen und dann anfangen, über reguläre Schlüssel-Wert-Paar-Zeilen im Vergleich zu Inline-Tabellen nachzudenken. Das ist natürlich nichts im Vergleich zu YAML. Hier ist eine aufschlussreiche Übung: Blättern Sie durch http://yaml.org/spec/1.2/spec.pdf und versuchen Sie herauszufinden, welche syntaktischen Einschränkungen für Schlüssel und Werte ohne Anführungszeichen in Schlüssel-Wert-Paaren gelten. Ich bin mir immer noch nicht ganz sicher. YAML bettet JSON als Teilmenge ein, aber hier hört es noch nicht auf. Soweit ich dem Dokument entnehmen kann, anstatt zu schreiben:

module: rsc.io/hello
require: 
- golang.org/x/text: v0.0.0-20180208041248-4e4a3210bb54
- rsc.io/quote: v1.5.2

es scheint ebenso gültig zu sein, zu schreiben:

%YAML 1.2
---
!!map {
 ? !!str "module" : !!str "rsc.io/hello"
 ? !!str "require" 
 : !!seq [
   !!map { ? !!str "golang.org/x/text" : !!str "v0.0.0-20180208041248-4e4a3210bb54" },
   !!map { ? !!str "rsc.io/quote" : !!str "v1.5.2" },
 ],
}

und es scheint auch, dass die beiden Formen willkürlich vermischt werden können. So einfach wie

module: !!str rsc.io/hello

scheint gültiges YAML zu sein, bedeutet jedoch etwas anderes als das, was unser "Teilmengen"-Parser verstehen würde. Es würde ständig Druck geben, das Beharren auf der Verwendung einer Teilmenge von YAML aufzugeben, und dennoch wird es schwieriger, einen guten mechanischen Editor (Parse+Edit+Reprint) zu schreiben, je komplexer die Einführung ist.

Wenn wir ein vorhandenes Format auswählen müssten, würde ich TOML wählen, aber selbst das scheint falsch zu sein:

module = "rsc.io/hello"

[require]
"golang.org/x/text" = "v0.0.0-20180208041248-4e4a3210bb54"
"rsc.io/quote" = "v1.5.2"

[[replace]]
"rsc.io/quote" = "v1.5.2"
with = "github.com/you/quote"
at = "v0.0.0-myfork"

Die [[ ]] sind hier notwendig, weil [require] eine einzelne Tabelle ist (von Schlüssel-Wert-Paaren, von denen jedes für sich steht), während [[replace]] ein Array von Tabellen ist, in denen jede Tabelle ein Ersatz mit drei ist Schlüssel: der zu ersetzende Pfad und die Sonderschlüssel „mit“ und „at“. Wenn Sie eine mögliche zukünftige Erweiterung reservieren möchten, müssen Sie auch [[erforderlich]] verwenden.

[[require]]
"golang.org/x/text" = "v0.0.0-20180208041248-4e4a3210bb54"

[[require]]
"rsc.io/quote" = "v1.5.2"

Alles in allem scheint es, als würden diese Dateiformate nicht wirklich dazu beitragen, unser Ziel zu erreichen, die Datei für Benutzer und Programme einfach zu bearbeiten. Wir müssten wahrscheinlich sowieso einen benutzerdefinierten Parser + Nachdrucker schreiben, daher wäre der einzige wirkliche Vorteil die Syntaxhervorhebung in Editoren. Ich denke, dieser Vorteil wird leicht durch die Unbeholfenheit aufgewogen, unsere Semantik überhaupt in diese Dateien zu stecken. Wenn Ihre Konfiguration aus wenigen grundlegenden Schlüssel-Wert-Paaren besteht, sind diese sehr sinnvoll. Wir haben nicht nur Schlüssel-Wert-Paare, daher machen diese Dateien keinen Sinn.

PS Ich habe mich lange gefragt, warum "dep secure -add" bestehende Einschränkungen in Gopkg.toml nicht geändert hat. Die Antwort ist, dass Dep handgeschriebenes TOML nicht zuverlässig modifizieren kann, um Kommentare und dergleichen zu erhalten. Dep hängt manchmal an Gopkg.toml an, erlegt aber ansonsten die Regel auf, dass Gopkg.toml im Besitz von Personen ist und Gopkg.lock im Besitz von Programmen ist. Dies scheint sowohl ein Artefakt der verfügbaren Bibliotheken als auch eine Designentscheidung zu sein.

Basierend auf (1) einer Diskussion mit Rob, (2) niemand, der auf meinen letzten Kommentar antwortet, und (3) den Emoji-Zählern für diesen Kommentar, werde ich dieses Problem schließen und die maßgeschneiderte Syntax in go.mod beibehalten (Betreff zur weiteren Verfeinerung wie das Ablegen von Anführungszeichen).

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen