web-dev-qa-db-fra.com

Comment casser une longue ligne de code dans Golang?

Venant de Python, je ne suis pas habitué à 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é juste de casser la ligne en frappant enter 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 je reçois encore:

syntax error: unexpected .

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

73
Karlom

D'abord un peu de fond. La grammaire formelle de Go utilise des points-virgules ";" en tant que terminateurs dans de nombreuses productions, mais les programmes Go peuvent en omettre la plupart (et ils devraient avoir une source plus claire et facilement lisible; gofmt supprime également les points-virgules inutiles).

La spécification énumère les règles exactes. Spec: Point-virgules:

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

  1. Lorsque l'entrée est décomposé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 clôture ")" ou "}".

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 la ligne suivante ne sera pas traitée comme la suite 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 cette position elle-même (sans la ligne précédente) est une erreur de compilation: syntax error: unexpected .

Vous pouvez donc rompre votre ligne à tout moment qui n’entre pas en conflit avec les règles énumérées au point 1. au dessus de.

Typiquement, vous pouvez casser vos lignes après une virgule ,, après ouverture parenthèse, par exemple. (, [, {, et après un point . qui peut référencer un champ ou une méthode d’une certaine valeur. Vous pouvez également interrompre 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 un littéral struct ou slice ou map répertoriant les valeurs initiales, et que vous souhaitez rompre la ligne après avoir répertorié la dernière valeur, vous devez insérer une virgule obligatoire , même s’il s’agit de la dernière valeur et qu’aucune autre ne suivra, par exemple:

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

Ceci est conforme aux règles du point-virgule et vous permet également de réorganiser et d'ajouter de nouvelles lignes sans avoir à prendre en charge l'ajout/la suppression de la virgule finale; par exemple. vous pouvez simplement échanger les 2 lignes sans avoir à supprimer et à ajouter une nouvelle virgule:

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

Il en va de même lorsque vous listez les arguments d'un appel de fonction:

fmt.Println("first",
    "second",
    "third",       // Note it ends with a comma
)
88
icza

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

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

15
tobyodavies

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

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

Comme mentionné, il s'agit d'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 je tire des enseignements, tout en conservant une partie de mon propre style.

Voici comment formater ceci:

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