¿Cómo romper una larga línea de código en Golang?


107

Viniendo de Python, no estoy acostumbrado a ver líneas de código de más de 80 columnas. Entonces, cuando me encuentro con esto:

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

Traté de romperlo para

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

Pero consigo

 syntax error: unexpected \

También intenté simplemente romper la línea presionando Enter y colocando un punto y coma al final:

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

Pero de nuevo obtengo:

syntax error: unexpected .

Entonces me pregunto cuál es la forma golangica de hacerlo.

Respuestas:


121

Primero algunos antecedentes. La gramática formal de Go utiliza punto ";"y coma como terminadores en muchas producciones, pero los programas de Go pueden omitir la mayoría de ellos (y deberían tener una fuente más clara y fácil de leer; gofmttambién elimina puntos y comas innecesarios).

La especificación enumera las reglas exactas. Especificaciones: punto y coma:

La gramática formal usa punto y coma ";" como terminadores en una serie de producciones. Los programas Go pueden omitir la mayoría de estos puntos y comas utilizando las siguientes dos reglas:

  1. Cuando la entrada se divide en tokens, se inserta automáticamente un punto y coma en el flujo de tokens inmediatamente después del token final de una línea si ese token es

  2. Para permitir que las declaraciones complejas ocupen una sola línea, se puede omitir un punto y coma antes de un ")" o "}" de cierre.

Entonces, como puede ver si inserta un carácter de nueva línea después del paréntesis ), ;se insertará un punto y coma automáticamente y, por lo tanto, la línea siguiente no se tratará como la continuación de la línea anterior. Esto es lo que sucedió en su caso, por lo que la siguiente línea que comienza con .Scan(&ReadUser.ID,...le dará un error en tiempo de compilación, ya que esta situación por sí sola (sin la línea anterior) es un error en tiempo de compilación:syntax error: unexpected .

Por lo tanto, puede romper su línea en cualquier punto que no entre en conflicto con las reglas enumeradas en el punto 1.anterior.

Normalmente, usted puede romper sus líneas después de la coma ,, después de la apertura entre paréntesis, por ejemplo (, [, {, y después de un punto .que puede estar haciendo referencia a un campo o método de algún valor. También puede romper su línea después de los operadores binarios (aquellos que requieren 2 operandos), por ejemplo:

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

Una cosa que vale la pena señalar aquí es que si tiene una estructura, corte o mapa literal que enumera los valores iniciales y desea romper la línea después de enumerar el último valor, debe poner una coma obligatoria ,aunque este sea el último valor y no seguirán más, por ejemplo:

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

Esto es para cumplir con las reglas del punto y coma, y ​​también para que pueda reorganizar y agregar nuevas líneas sin tener que ocuparse de agregar / quitar la coma final; por ejemplo, puede simplemente intercambiar las 2 líneas sin tener que eliminar y agregar una nueva coma:

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

Lo mismo se aplica cuando se enumeran los argumentos para una llamada de función:

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

3
Sigo poniendo una coma al final de los literales de JavaScript. #hatejs
Paulo Scardine

26
TL; DR: Por lo general, puede dividir las líneas después de la coma, después de abrir el paréntesis, por ejemplo (, [, {, y después de un punto. Que puede hacer referencia a un campo o método de algún valor.
Peeter Kokk

2
Tener que agregar una coma adicional al final me recuerda algunos errores antiguos de IE js, terrible
Christophe Roussy

4
@ChristopheRoussy Es subjetivo, me encanta que todas las líneas tengan que terminar con una coma, y ​​puedo reorganizar y agregar nuevas líneas con facilidad sin tener que ocuparme de agregar / eliminar comas.
icza

@icza, también me gusta que terminen con una coma, pero no tener que hacerlo para el último :)
Christophe Roussy

22

La forma más sencilla es simplemente dejar el operador ( .) en la primera línea.

\ Las continuaciones de línea también se desaconsejan en muchas guías de estilo de Python, puede envolver toda la expresión en parens si se mueve hacia adelante y hacia atrás entre go y python, ya que esta técnica funciona en ambos idiomas.


Buen consejo sobre dejar al operador al final. Funcionó.
Karlom

1
envolver entre paréntesis no funciona en go afaik. Ir todavía inserta el punto y coma entre paréntesis
Adrian Shum

Lo intenté y Go realmente inserta un punto y coma invisible, incluso entre paréntesis. Entonces esto solo funciona en Python, no en Go.
Roland Illig

@RolandIllig Esto definitivamente funciona: play.golang.org/p/oFKaxLTphU
tobyodavies

Perdón por mi redacción, me refería al uso de paréntesis (pero no escribí eso). Envolver la expresión entre paréntesis puede funcionar en Python, pero no funciona en Go.
Roland Illig

16

Es cuestión de estilo, pero me gusta:

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

16

Como se mencionó, esto es una cuestión de preferencia de estilo. Entiendo que los creadores de Go han sugerido un estilo basado en su experiencia del cual yo aprendo, pero también guardo algo de mi propio estilo de mi experiencia.

A continuación se muestra cómo formatearía esto:

err := database.
  QueryRow("select * from users where user_id=?", id).
  Scan(
    &ReadUser.ID,
    &ReadUser.Name,
    &ReadUser.First,
    &ReadUser.Last,
    &ReadUser.Email,
  )
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.