Comment casser une longue ligne de code dans Golang?

107

Venant de Python, je n'ai pas l'habitude de voir des lignes de code de plus de 80 colonnes. Alors, quand je rencontre ceci:

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

J'ai essayé de le casser pour

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

Mais je reçois

 syntax error: unexpected \

J'ai aussi essayé de casser la ligne en appuyant sur Entrée et de mettre un point-virgule à la fin:

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

Mais le je reçois à nouveau:

syntax error: unexpected .

Alors je me demande quelle est la manière golangique de le faire?

Karlom
la source

Réponses:

121

Tout d'abord un peu de contexte. La grammaire formelle de Go utilise des points-virgules ";"comme terminateurs dans de nombreuses productions, mais les programmes Go peuvent omettre la plupart d'entre eux (et ils devraient avoir une source plus claire et facilement lisible; gofmtsupprime également les points-virgules inutiles).

La spécification répertorie les règles exactes. Spec: Points-virgules:

La grammaire formelle utilise des points-virgules ";" comme terminateurs dans un certain nombre de productions. Les programmes Go peuvent omettre la plupart de ces points-virgules en utilisant les deux règles suivantes:

  1. Lorsque l'entrée est divisée en jetons, un point-virgule est automatiquement inséré dans le flux de jetons immédiatement après le jeton final d'une ligne si ce jeton est

  2. Pour permettre aux instructions complexes d'occuper une seule ligne, un point-virgule peut être omis avant une fermeture ")" ou "}".

Ainsi, comme vous pouvez le voir si vous insérez un caractère de nouvelle ligne après la parenthèse ), un point-virgule ;sera inséré automatiquement et ainsi la ligne suivante ne sera pas traitée comme la continuation de la ligne précédente. C'est ce qui s'est passé dans votre cas, et donc la ligne suivante commençant par .Scan(&ReadUser.ID,...vous donnera une erreur de compilation car cela en soi (sans la ligne précédente) est une erreur de compilation:syntax error: unexpected .

Vous pouvez donc rompre votre ligne à tout moment qui n'est pas en conflit avec les règles énumérées 1.au point ci-dessus.

En général , vous pouvez briser vos lignes après la virgule ,, après l' ouverture entre parenthèses , par exemple (, [, {et après un point .qui peut être référence à une méthode ou champ d' une certaine valeur. Vous pouvez également couper votre ligne après les opérateurs binaires (ceux qui nécessitent 2 opérandes), par exemple:

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

Une chose à noter ici est que si vous avez une structure ou une tranche ou une carte littérale répertoriant les valeurs initiales, et que vous souhaitez couper la ligne après avoir répertorié la dernière valeur, vous devez mettre une virgule obligatoire ,même s'il s'agit de la dernière valeur et non d'autres suivront, par exemple:

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

C'est pour se conformer aux règles du point-virgule, et aussi pour que vous puissiez réorganiser et ajouter de nouvelles lignes sans avoir à prendre soin d'ajouter / supprimer la virgule finale; par exemple, vous pouvez simplement permuter les 2 lignes sans avoir à supprimer et à ajouter une nouvelle virgule:

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

La même chose s'applique lors de la liste des arguments d'un appel de fonction:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)
icza
la source
3
Je continue de mettre une virgule à la fin des littéraux javascript. #hatejs
Paulo Scardine
26
TL; DR: En général, vous pouvez couper vos lignes après la virgule ,, après l'ouverture des parenthèses, par exemple (, [, {, et après un point. Qui peut faire référence à un champ ou à une méthode d'une certaine valeur.
Peeter Kokk
2
Le fait de devoir ajouter une virgule supplémentaire à la fin me rappelle quelques vieux bugs IE js, terrible
Christophe Roussy
4
@ChristopheRoussy C'est subjectif, j'adore que toutes les lignes doivent se terminer par une virgule, et je peux réorganiser et ajouter de nouvelles lignes facilement sans avoir à prendre soin d'ajouter / supprimer des virgules.
icza
@icza, j'aime aussi qu'ils se terminent par une virgule, mais ne pas avoir à le faire pour le dernier :)
Christophe Roussy
22

Le moyen le plus simple est de laisser simplement l'opérateur ( .) sur la première ligne.

\ les continuations de ligne sont également déconseillées dans de nombreux guides de style python, vous pouvez envelopper l'expression entière dans des parenthèses si vous vous déplacez entre go et python car cette technique fonctionne dans les deux langues.

tobyodavies
la source
Bonne astuce pour quitter l'opérateur à la fin. Ça a marché.
Karlom
1
la mise entre parenthèses ne fonctionne pas dans go afaik. Allez toujours insérer le point-virgule entre parenthèses
Adrian Shum
Je viens de l'essayer et Go insère vraiment un point-virgule invisible, même entre parenthèses. Donc, cela ne fonctionne qu'en Python, pas en Go.
Roland Illig
@RolandIllig Cela fonctionne définitivement: play.golang.org/p/oFKaxLTphU
tobyodavies
Désolé pour mon libellé, je faisais référence à l'utilisation de parenthèses (mais je n'ai pas écrit cela). L'encapsulation de l'expression entre parenthèses peut fonctionner en Python, mais ne fonctionne pas en Go.
Roland Illig
16

C'est une question de style, mais j'aime:

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

Comme mentionné, c'est une question de préférence de style. Je comprends que les créateurs de Go ont suggéré un style basé sur leur expérience dont j'apprends mais gardent également une partie de mon propre style de mon expérience.

Voici comment je formaterais ceci:

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