Wie kann man in Golang eine lange Codezeile durchbrechen?

106

Ich komme aus Python und sehe keine Codezeilen, die länger als 80 Spalten sind. Wenn ich also auf Folgendes stoße:

err := database.QueryRow("select * from users where user_id=?", id).Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

Ich habe versucht, es zu brechen

err := database.QueryRow("select * from users where user_id=?", id) \
    .Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email)

Aber ich verstehe

 syntax error: unexpected \

Ich habe auch versucht, die Linie mit der Eingabetaste zu durchbrechen und am Ende ein Semikolon einzufügen:

err := database.QueryRow("select * from users where user_id=?", id) 
.Scan(&ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email);

Aber das bekomme ich wieder:

syntax error: unexpected .

Also frage ich mich, wie das golangisch geht?

Karlom
quelle

Antworten:

120

Zuerst einige Hintergrundinformationen. Die formale Grammatik von Go verwendet ";"in vielen Produktionen Semikolons als Terminatoren, aber Go-Programme lassen möglicherweise die meisten davon weg (und sie sollten eine klarere, leicht lesbare Quelle haben;gofmt entfernt auch unnötige Semikolons).

In der Spezifikation sind die genauen Regeln aufgeführt. Spezifikation: Semikolons:

Die formale Grammatik verwendet Semikolons ";" als Terminatoren in einer Reihe von Produktionen. Go-Programme können die meisten dieser Semikolons nach den folgenden zwei Regeln weglassen:

  1. Wenn die Eingabe in Token aufgeteilt wird, wird unmittelbar nach dem letzten Token einer Zeile automatisch ein Semikolon in den Token-Stream eingefügt, wenn dies der Fall ist

  2. Damit komplexe Anweisungen eine einzelne Zeile belegen können, kann vor einem schließenden ")" oder "}" ein Semikolon weggelassen werden.

Wie Sie sehen können, wenn Sie nach der Klammer ein Zeilenumbruchzeichen einfügen ), ;wird automatisch ein Semikolon eingefügt, sodass die nächste Zeile nicht als Fortsetzung der vorherigen Zeile behandelt wird. Dies ist in Ihrem Fall geschehen, und daher .Scan(&ReadUser.ID,...gibt Ihnen die nächste Zeile, die mit beginnt , einen Fehler bei der Kompilierung, da dieser für sich steht (ohne die vorherige Zeile) ist ein Fehler bei der Kompilierung:syntax error: unexpected .

Sie können Ihre Linie also an jedem Punkt brechen, der nicht mit den unter Punkt 1.oben aufgeführten Regeln in Konflikt steht .

Normalerweise können Sie Ihre Linien hinter dem Komma brechen ,, nach dem Öffnen Klammer zum Beispiel (, [, {und nach einem Punkt , .die ein Feld oder eine Methode von einigem Wert sein können referenzieren. Sie können Ihre Zeile auch nach binären Operatoren (die 2 Operanden erfordern) unterbrechen, z.

i := 1 +
        2
fmt.Println(i) // Prints 3

Hier ist zu beachten, dass Sie ein obligatorisches Komma setzen müssen, wenn Sie ein Struktur-, Slice- oder Map-Literal haben, in dem die Anfangswerte aufgelistet sind, und nach dem Auflisten des letzten Werts die Linie unterbrechen möchten, ,obwohl dies der letzte Wert und Nein ist Weitere werden folgen, zB:

s := []int {
    1, 2, 3,
    4, 5, 6,  // Note it ends with a comma
}

Dies entspricht den Semikolonregeln und ermöglicht es Ihnen, neue Zeilen neu anzuordnen und hinzuzufügen, ohne sich um das Hinzufügen / Entfernen des endgültigen Kommas kümmern zu müssen. Sie können beispielsweise einfach die 2 Zeilen austauschen, ohne ein neues Komma entfernen und hinzufügen zu müssen:

s := []int {
    4, 5, 6,
    1, 2, 3,
}

Gleiches gilt für die Auflistung von Argumenten zu einem Funktionsaufruf:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)
icza
quelle
3
Ich setze immer ein Komma am Ende von Javascript-Literalen. #hatejs
Paulo Scardine
25
TL; DR: Normalerweise können Sie Ihre Zeilen nach dem Komma brechen, nachdem Sie die Klammer geöffnet haben, z. B. (, [, {und nach einem Punkt, der möglicherweise auf ein Feld oder eine Methode mit einem bestimmten Wert verweist.
Peeter Kokk
2
Das Hinzufügen eines zusätzlichen Kommas am Ende erinnert mich an einige alte IE-Fehler, die schrecklich sind
Christophe Roussy
4
@ChristopheRoussy Es ist subjektiv, ich liebe es, dass alle Zeilen mit einem Komma enden müssen, und ich kann problemlos neue Zeilen neu anordnen und hinzufügen, ohne mich um das Hinzufügen / Entfernen von Kommas kümmern zu müssen.
icza
@icza, ich mag es auch, wenn sie mit einem Komma enden, aber es nicht für das letzte tun müssen :)
Christophe Roussy
22

Am einfachsten ist es, den Operator ( .) in der ersten Zeile zu belassen.

\ In vielen Python-Stilrichtlinien wird auch von Zeilenfortsetzungen abgeraten. Sie können den gesamten Ausdruck in Parens einschließen, wenn Sie zwischen go und python hin und her wechseln, da diese Technik in beiden Sprachen funktioniert.

tobyodavies
quelle
Netter Tipp, den Bediener am Ende zu verlassen. Es funktionierte.
Karlom
1
Das Einwickeln in Klammern funktioniert in go afaik nicht. Fügen Sie immer noch das Semikolon in Klammern ein
Adrian Shum
Ich habe es gerade versucht und Go fügt wirklich ein unsichtbares Semikolon ein, sogar in Klammern. Das funktioniert also nur in Python, nicht in Go.
Roland Illig
@ RolandIllig Das funktioniert definitiv: play.golang.org/p/oFKaxLTphU
tobyodavies
Entschuldigung für meinen Wortlaut, ich bezog mich auf die Verwendung von Klammern (habe das aber nicht geschrieben). Das Umschließen des Ausdrucks in Klammern funktioniert möglicherweise in Python, in Go jedoch nicht.
Roland Illig
16

Es ist eine Frage des Stils, aber ich mag:

err := database.QueryRow(
    "select * from users where user_id=?", id,
).Scan(
    &ReadUser.ID, &ReadUser.Name, &ReadUser.First, &ReadUser.Last, &ReadUser.Email,
)
peterSO
quelle
16

Wie bereits erwähnt, ist dies eine Frage der Stilpräferenz. Ich verstehe, dass die Macher von Go einen Stil vorgeschlagen haben, der auf ihren Erfahrungen basiert, aus denen ich lerne, aber auch einen Teil meines eigenen Stils aus meinen Erfahrungen beibehält.

Unten ist, wie ich dies formatieren würde:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
Halorium
quelle